Android告诉我我的位图在我实际回收之前已经回收了

时间:2015-01-05 06:17:48

标签: java android memory bitmap recycle

我从XML获取我的位图:

//Get bitmap from drawable
bd = (BitmapDrawable) view.getResources().getDrawable(R.drawable.backgrounds);
backgrounds = bd.getBitmap();

//Do required work with bitmap (Will just use a log statement here for testing
Log.v("NewTag","Testing: "+bd.getBitmap().getPixel(0, 0));

//Now recycle this large bitmap
bd.getBitmap.recycle();
bd=null;
backgrounds.recycle();
backgrounds=null;

我第一次运行此代码时,一切都很好。但是,当我退出我的应用程序(使用后退键),然后重新启动应用程序时,它可能或可能不会工作。有时候,我收到一个错误:

  

无法在循环位图上调用getPixel()

为什么呢?我还没有回收它。或者更确切地说,它似乎不是重新创建位图并记住上次回收。

如果我使用BitmapFactory获取位图,这个问题不会发生(遗憾的​​是,我不能这样做,因为我必须从XML别名中获取这个特定的位图)。

在安装Lollipop之前,这个工作正常(只要我有bd = null)。

我已经连续两天遇到这个问题,所以如果有人可以对它发光,我会非常感激。

修改

我试图@ aga建议不要回收/归零bd,但这没什么区别。位图仍然已经是'它很快被重新创造(再次,间歇地)。

此外,当这样记录时:

Log.v("NewTag","Backgrounds: "+backgrounds);

我注意到失败时,记录的引用与上一次相同。所以.....

enter image description here

3 个答案:

答案 0 :(得分:5)

Resources班级有caches for resources loaded from your APK。当您回收DrawableBitmap时,会破坏缓存的对象。 Resources缓存无法知道这一点,所以当您下次请求该资源时,他们会愉快地返回相同的对象。

当您的应用程序进程终止时,所有内存状态都将丢失,包括资源缓存 - 因此事情将再次起作用(一次)。请注意,“退出”应用程序或销毁活动并不一定意味着您的流程将会死亡。

答案 1 :(得分:2)

有趣的问题。我很确定,Android背后有一些优化的想法。

如果执行需要XML的位图:

    Resources res = new Resources(getAssets(), new DisplayMetrics(), new Configuration());

    bd = (BitmapDrawable) res.getDrawable(R.drawable.bitmap_drawable);
    backgrounds = bd.getBitmap();

    ......

    bd.getBitmap().recycle();
    bd=null;
    backgrounds.recycle();
    backgrounds=null;

Optionaly,您可以先尝试从标准Bitmap获取getResources(),然后再实例化新资源实例。

如果您需要XML的位图:

 Bitmap backgrounds = BitmapFactory.decodeResource(getResources(), R.drawable.test_image);

获取图片和

 backgrounds.recycle();
 backgrounds=null;

回收它。

我希望,这有帮助。

答案 2 :(得分:0)

正如@snild Dolkow所述,出现这种情况的原因是位图存储在资源缓存中,当您尝试再次获取位图时,您将获得回收的位图。

我认为解决方案是save the bitmap to internal storagereload it from storage

此解决方案的开销是您在使用完毕后必须删除该图像文件。