【发布时间】:2014-10-12 23:23:38
【问题描述】:
最近,我开始使用 Google ImageWorker 类在后台线程上加载位图。此类处理所有事情,包括将位图放入 ImageView。谷歌在这里谈论这个类(它是图像操作和缓存的辅助类):http://developer.android.com/training/displaying-bitmaps/process-bitmap.html
在我的例子中,ImageView(s) 是 ListView 中列表项的一部分。这是我的 ArrayAdapter 上 getView 的有趣部分:
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView == null ? inflater.inflate(R.layout.nodelist_item, null) : convertView;
NodeHolder holder = getHolder(view);
Node node = mList.get(position);
holder.txtTitle.setText(node.Title);
//Setting the rest of the different fields ...
//And finally loading the image
if(node.hasArt())
worker.loadImage(node.ImageID, holder.imgIcon);
}
完整的getView方法可以看这里:http://pastebin.com/CJbtVfij
worker 对象是 ImageWorker 的一个非常简单的实现:
public class NodeArtWorker extends ImageWorker {
protected int width;
protected int height;
public NodeArtWorker(Context context) {
super(context);
addImageCache(context);
//Code for getting the approximate width and height of the ImageView, in order to scale to save memory.
}
@Override
protected Bitmap processBitmap(Object data) {
Bitmap b = getBitmap(data);
if(b == null) return null;
return Utils.resizeBitmap(b, width, height);
}
protected Bitmap getBitmap(Object data) {
//Downloads the bitmap from a server, and returns it.
}
}
这很好用,现在的性能比以前好多了。但是,如果我更改列表中某些项目的 ImageID,并调用 adapter.notifyDataSetChanged() 来重建视图(从而开始加载新位图),我会收到 RuntimeException:
0 java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@41adf448
1 at android.graphics.Canvas.throwIfRecycled(Canvas.java:1058)
2 at android.graphics.Canvas.drawBitmap(Canvas.java:1159)
3 at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:440)
4 at android.widget.ImageView.onDraw(ImageView.java:1025)
5 at android.view.View.draw(View.java:14126)
完整的堆栈跟踪可以在以下 pastebin 条目中看到,但可能并不有趣,因为它是典型的 Android 视图层次结构重绘堆栈跟踪:http://pastebin.com/DsWcidqw
我知道位图正在被回收,但我不明白究竟在哪里以及可以做些什么。由于我的代码直接来自 Google,而且据我所知,这是推荐的执行方式,我很困惑。
【问题讨论】:
-
你能描述一下
Node和NodeHolder的结构吗 -
它位于第一个代码块正下方的 pastebin 中。 :)
标签: android caching memory-management android-listview bitmap