Създавам проста джаджа за Android, която извлича и показва обложки на някои филми от уебсайт. Това е просто GridView
, което показва изображенията. Приспособлението работи добре, но в момента, в който започна да превъртам, получавам OutOfMemoryError
и Android убива моя процес.
Ето кода на моя RemoteViewsFactory
. Изглежда не мога да разбера как да разреша това. Изображенията, които използвам, са с подходящ размер, така че да не губя памет в Android. Те са с идеални размери. Както можете да видите, използвам много малък LRU кеш и в моя манифест дори съм активирал android:largeHeap="true"
. Блъскам главата си по този въпрос цели два дни и се чудя дали това, което се опитвам да направя, изобщо е възможно?
public class SlideFactory implements RemoteViewsFactory {
private JSONArray jsoMovies = new JSONArray();
private Context ctxContext;
private Integer intInstance;
private RemoteViews remView;
private LruCache<String, Bitmap> lruCache;
private static String strCouch = "http://192.168.1.110:5984/movies/";
public SlideFactory(Context ctxContext, Intent ittIntent) {
this.ctxContext = ctxContext;
this.intInstance = ittIntent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
this.lruCache = new LruCache<String, Bitmap>(4 * 1024 * 1024);
final Integer intMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
final Integer intBuffer = intMemory / 8;
lruCache = new LruCache<String, Bitmap>(intBuffer) {
@Override
protected int sizeOf(String strDigest, Bitmap bmpCover) {
return bmpCover.getByteCount() / 1024;
}
};
}
public RemoteViews getViewAt(int intPosition) {
if (intPosition <= getCount()) {
try {
String strDocid = this.jsoMovies.getJSONObject(intPosition).getString("id");
String strDigest = this.jsoMovies.getJSONObject(intPosition).getJSONObject("value").getJSONObject("_attachments").getJSONObject("thumb.jpg").getString("digest");
String strTitle = this.jsoMovies.getJSONObject(intPosition).getJSONObject("value").getString("title");
Bitmap bmpThumb = this.lruCache.get(strDigest);
if (bmpThumb == null) {
String strUrl = strCouch + strDocid + "/thumb.jpg";
System.out.println("Fetching" + intPosition);
bmpThumb = new ImageFetcher().execute(strUrl).get();
this.lruCache.put(strDigest, bmpThumb);
}
remView.setImageViewBitmap(R.id.movie_cover, bmpThumb);
remView.setTextViewText(R.id.movie_title, strTitle);
} catch (Exception e) {
e.printStackTrace();
}
return remView;
}
return null;
}
public void onCreate() {
return;
}
public void onDestroy() {
jsoMovies = null;
}
public int getCount() {
return 20;
}
public RemoteViews getLoadingView() {
return null;//new RemoteViews(this.ctxContext.getPackageName(), R.layout.loading);
}
public int getViewTypeCount() {
return 1;
}
public long getItemId(int intPosition) {
return intPosition;
}
public boolean hasStableIds() {
return true;
}
public void onDataSetChanged() {
this.remView = new RemoteViews(this.ctxContext.getPackageName(), R.layout.slide);
try {
DefaultHttpClient dhcNetwork = new DefaultHttpClient();
String strUrl = strCouch + "_design/application/_view/language?" + URLEncoder.encode("descending=true&startkey=[\"hi\", {}]&attachments=true");
HttpGet getMovies = new HttpGet(strUrl);
HttpResponse resMovies = dhcNetwork.execute(getMovies);
Integer intMovies = resMovies.getStatusLine().getStatusCode();
if (intMovies != HttpStatus.SC_OK) {
throw new HttpResponseException(intMovies, "Server responded with an error");
}
String strMovies = EntityUtils.toString(resMovies.getEntity(), "UTF-8");
this.jsoMovies = new JSONObject(strMovies).getJSONArray("rows");
} catch (Exception e) {
Log.e("SlideFactory", "Unknown error encountered", e);
}
}
}
Ето източника на AsyncTask
, който извлича изображенията:
public class ImageFetcher extends AsyncTask<String, Void, Bitmap> {
@Override
protected Bitmap doInBackground(String... strUrl) {
Bitmap bmpThumb = null;
try {
URL urlThumb = new URL(strUrl[0]);
HttpURLConnection hucConnection = (HttpURLConnection) urlThumb.openConnection();
InputStream istThumb = hucConnection.getInputStream();
bmpThumb = BitmapFactory.decodeStream(istThumb);
istThumb.close();
hucConnection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
return bmpThumb;
}
}
ImageFetcher
? Можете ли да посочите и размера на изображенията, които зареждате (или може би размера на най-голямото сред тях)..?? - person Amulya Khare   schedule 22.11.2013ImageFetcher
. Мога да си поиграя с размера на извадката, но това драстично намалява качеството. Всичките ми изображения са 250x375 пиксела. Поставямprintln
в методаgetViewAt
и забелязвам, че Android се опитва да зареди всички изображения наведнъж, въпреки че само няколко изображения се виждат вGridView
. Мислех, че начинът, по който работят тези адаптери заListView
,GridView
иStackVIew
е, че те зареждат предварително само няколко елемента и в момента, в който потребителят превърти и те излязат от фокус, Android изхвърля старите оформления. Не виждам защо се опитва да зареди всички елементи. - person Mridang Agarwalla   schedule 22.11.2013this.lruCache = new LruCache<String, Bitmap>(4 * 1024 * 1024);
ред е безполезен. - person Leonidos   schedule 22.11.2013LRUCache
от моя код, но не помогна. - person Mridang Agarwalla   schedule 22.11.2013setImageViewBitmap
, моля, публикувайте го! Изобщо няма информация за това! - person anil   schedule 23.06.2015