【发布时间】:2013-12-02 00:51:50
【问题描述】:
我正在创建一个简单的 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;
}
}
【问题讨论】:
-
@commonsware,您能对此有所了解吗?你一直都有答案。 :) 谢谢。
-
你能发布一些 logcat 输出吗?
-
@MridangAgarwalla 你能发布
ImageFetcher的代码吗?您还可以提及您正在加载的图像的大小(或者可能是其中最大的大小)..?? -
@AmulyaKhare,我已经发布了
ImageFetcher的来源。我可以使用样本大小,但它会大大降低质量。我的图像都是 250x375 像素。我将println放入方法getViewAt方法中,并注意到Android 尝试一次加载所有图像,即使GridView中只有少数图像可见。我认为ListView、GridView和StackVIew的这些适配器的工作方式是它们只预加载一些项目,并且当用户滚动并且它们失去焦点时,Android 会丢弃旧的布局。我不明白为什么它会尝试加载所有项目。 -
Have you read it? 而这条
this.lruCache = new LruCache<String, Bitmap>(4 * 1024 * 1024);行没用。
标签: java android android-gridview android-appwidget android-remoteview