Я создаю простой виджет для 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