关于Canvas: trying to use a recycled bitmap android.graphics的疑惑

summersrest 2014-07-04 10:14:09
因为viewpager图片内存溢出的问题,不得不考虑手动释放内存,不过出的问题我不理解。

我的想法是创建一个Map,然后用instantiateItem中的参数arg0当作键,bitmap当作值,当destroyItem中去掉VIew的时候我捎带着把不再用到的bitmap也回收掉
//这个是存bitmap的map
public HashMap<Integer, SoftReference<Bitmap>> cacheBit;

adapter中大概的相关代码是这样的:

//这个是destroyItem中回收代码
// 这里进行回收,当我们左右滑动的时候,会把早期的图片回收掉.
public void destroyItem(View arg0, int arg1, Object arg2) {
// TODO Auto-generated method stub
View view = (View) arg2;
((ViewPager) arg0).removeView(view);
//回收图片的代码
if (cacheBit.containsKey(arg1)) {
try {
Bitmap bm = cacheBit.get(arg1).get();
if (null != bm && !bm.isRecycled()) {
bm.recycle();
bm = null;
}
// 提醒系统回收图片
System.gc();
} catch (Exception e) {
// TODO: handle exception
System.out.println("图片已被回收");
}

cacheBit.remove(arg1);

}
}

//然后这个是加载view的页面,在这个方法中我将bitmap存入map中,方便回收:
public Object instantiateItem(View arg0, int arg1) {
// TODO Auto-generated method stub
//这一部分是不相关的代码
View view;
LayoutInflater inflater = LayoutInflater.from(context);
view = inflater.inflate(R.layout.headingline_slider, null);
relative = (RelativeLayout) view.findViewById(R.id.bg);

//这里是图片的异步加载
// 根据图片URL去查找内存缓存有没有对应的Bitmap对象,并传递回调方法,如果没有,则等下载完毕回调
Bitmap bitmap = ImageLoader.loadBitmap(relative, list.get(arg1), new ImageCallBack() {
@Override
public void imageLoad(RelativeLayout relative, Bitmap bitmap) {
// TODO Auto-generated method stub
relative.setBackgroundDrawable(new BitmapDrawable(bitmap));
}
});
if (bitmap == null) {
relative.setBackgroundDrawable(new BitmapDrawable(bt));
} else {
relative.setBackgroundDrawable(new BitmapDrawable(bitmap));
}

// 将bitmap加载到map中,方便用过之后回收掉
cacheBit.put(arg1, new SoftReference<Bitmap>(bitmap));

((ViewPager) arg0).addView(view);
return view;
}



逻辑上我不知道哪里的错误,但是结果执行出来滑几次以后就会报一个异常,说我试图使用已回收的图片,不理解
Canvas: trying to use a recycled bitmap android.graphics.Bitmap@4054d588
...全文
1449 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
fznf1010 2015-10-20
  • 打赏
  • 举报
回复
有用! 感谢! 我这里也是在使用ImageLoader加载图片的同时另外手动添加图片回收处理 导致异常. 注释掉手动添加的图片回收处理就好了.
倾风gogo 2014-09-17
  • 打赏
  • 举报
回复
已解决 imageloader 有清除缓存的方法
倾风gogo 2014-09-17
  • 打赏
  • 举报
回复
你好,我同意的也遇到了这个问题,我想请教下 imageloader 你后来是怎么处理的?
老科达 2014-07-04
  • 打赏
  • 举报
回复
如果有相同的url 你要控制图片的引用计数 只有为0 你才能回收。
老科达 2014-07-04
  • 打赏
  • 举报
回复
有显示相同的图片的情况么(图片url 是一样的。)? 比如 你被摧毁的图片在当前item上使用, 这样就会导致图片被recycle 而你的控件正在使用这个图片绘制。
summersrest 2014-07-04
  • 打赏
  • 举报
回复
引用 7 楼 davidleen29 的回复:
根据代码看,你应该是使用ImageLoader 这个第三方的工具, 基本上比较完善的工具都会提供图片缓存机制,并有比较完善的淘汰算法。 当你的item摧毁时候,你recyle bitmap,但是对于imageLoader 它不知这个图片recycle了,就有可能同样的url 他返回的还是这个recycled 的图片。 你检查下。
你说的非常对,厉害啊,你这么以提示我真的发现问题了,果然是我考虑的不周全的问题,bitmap做过两次缓存,在adapter中一次,在imageLoader 里面也缓存过一次,adapter中的代码没有问题,但是adapter中回收了以后imageLoader 中并不知道已经被回收掉,根据键值判断该bitmap存在,但事实上该bitmap已被回收掉。所以报错了。知道错在哪里了,和你说的一模一样,非常感谢。希望见到过这个帖子的人别和我犯同样的错误了。
老科达 2014-07-04
  • 打赏
  • 举报
回复
根据代码看,你应该是使用ImageLoader 这个第三方的工具, 基本上比较完善的工具都会提供图片缓存机制,并有比较完善的淘汰算法。 当你的item摧毁时候,你recyle bitmap,但是对于imageLoader 它不知这个图片recycle了,就有可能同样的url 他返回的还是这个recycled 的图片。 你检查下。
老科达 2014-07-04
  • 打赏
  • 举报
回复
Bitmap bitmap = ImageLoader.loadBitmap(relative, list.get(arg1), new ImageCallBack() { @Override public void imageLoad(RelativeLayout relative, Bitmap bitmap) { // TODO Auto-generated method stub relative.setBackgroundDrawable(new BitmapDrawable(bitmap)); } }); if (bitmap == null) { relative.setBackgroundDrawable(new BitmapDrawable(bt)); } else { relative.setBackgroundDrawable(new BitmapDrawable(bitmap)); } // 将bitmap加载到map中,方便用过之后回收掉 cacheBit.put(arg1, new SoftReference<Bitmap>(bitmap)); / 这里 你有可能将bitmap=null 缓存进cache中。 //初始化时候 你的 bitmap 必然 为null ,但是你依然将这个null 写入缓存
summersrest 2014-07-04
  • 打赏
  • 举报
回复
引用 2 楼 davidleen29 的回复:
如果有相同的url 你要控制图片的引用计数 只有为0 你才能回收。
按照我的想法,应该是重新创建一个bitmap,然后再压入map中,不是这样的吗?
summersrest 2014-07-04
  • 打赏
  • 举报
回复
引用 2 楼 davidleen29 的回复:
如果有相同的url 你要控制图片的引用计数 只有为0 你才能回收。
听你这么一说好像是这么回事,被回收掉的再次引用就会报错。比如我滑倒第3张,第0张被回收了.当我往回滑再次加载第0张的时候报错了,好像确实是这样的。这是为什么呢?
summersrest 2014-07-04
  • 打赏
  • 举报
回复
引用 1 楼 davidleen29 的回复:
有显示相同的图片的情况么(图片url 是一样的。)? 比如 你被摧毁的图片在当前item上使用, 这样就会导致图片被recycle 而你的控件正在使用这个图片绘制。
没有图片相同的情况,服务器给出的图片是不相同的,不知道自己的想法错在哪里。

80,350

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧