我正在尝试为Android创建缓存图像系统,但内存消耗只会增长和增长。我查看了Android website的一些想法,但这个问题并不想消失。
以下是我从SD卡获取图像,设置并稍后销毁的代码。 我做错了什么?
WeakReference<Bitmap> newImageRef;
public void setImageFromFile(File source){
if(source.exists()){
Bitmap newImage = BitmapFactory.decodeFile(source.getAbsolutePath());
newImageRef = new WeakReference<Bitmap>(newImage);
if(newImage != null){
this.setImageBitmap(newImage);
}
}
}
@Override
protected void onDetachedFromWindow() {
Bitmap newImage = newImageRef.get();
if (newImage != null) {
newImage.recycle();
newImage = null;
}
Drawable drawable = getDrawable();
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
Bitmap bitmap = bitmapDrawable.getBitmap();
if (bitmap != null){
bitmap.recycle();
}
}
this.setImageResource(0);
newImage = null;
newImageRef = null;
System.gc();
super.onDetachedFromWindow();
}
答案 0 :(得分:2)
如果您使用的是Android版本&gt; 3.0,则无需调用recycle()
,因为只要没有对它的引用,gc就会自行清理位图。因此,删除回收电话是安全的。他们在这里什么都不做。
您发布的代码看起来很整洁但是您确定泄漏不会发生在其他地方。使用Android Memory Analyzer工具查看泄漏发生的位置,然后发布信息。
祝你好运。答案 1 :(得分:1)
尝试使用Drawable.setCallback(null);
。在Android 3.0或更高版本中,由于比早期版本更多的自动内存管理或垃圾收集,您甚至不需要recycle
。另见this。它具有关于Android中位图内存管理的良好信息。
答案 2 :(得分:0)
在此代码中,很难检查是否存在详细的错误,因为这似乎是“完全缓存”的简化版本。至少你提供的几行似乎没问题。
主要问题是在处理Bitmaps时GC似乎有点奇怪。如果您只是删除硬引用,它有时会挂在Bitmaps上一段时间,可能是因为Bitmap对象的分配方式。如前所述,在Android 3+上不需要回收。因此,如果要添加大量的位图,可能需要一些时间才能再次释放此内存。或者内存泄漏可能是代码的另一部分。对于复杂的问题,例如在重新实施之前检查已经过验证的解决方案是明智的。
这让我想到了第二个问题:使用弱引用。这可能不是针对主要问题,但通常不是用于android doc所写的Android 2.3+中的图像缓存的好模式:
注意:过去,流行的内存缓存实现是SoftReference或WeakReference位图缓存,但不建议这样做。从Android 2.3(API级别9)开始,垃圾收集器更积极地收集软/弱引用,这使得它们相当无效。此外,在Android 3.0(API Level 11)之前,位图的后备数据存储在本机内存中,而该内存未以可预测的方式发布,可能导致应用程序短暂超出其内存限制并崩溃。
现在的方法是使用LRU缓存,这在caching提供的链接中有详细解释。