为了解决您的困境,我相信这是预期的行为。
如果您想释放内存,您可以偶尔调用System.gc()
,但实际上您应该在大多数情况下让它管理垃圾收集本身。
我建议您保留某种简单的缓存(URL/文件名到位图),通过计算每个位图占用的字节数来跟踪自己的内存使用情况。
/**
* Estimates size of Bitmap in bytes depending on dimensions and Bitmap.Config
* @param width
* @param height
* @param config
* @return
*/
public static long estimateBitmapBytes(int width, int height, Bitmap.Config config){
long pixels=width*height;
switch(config){
case ALPHA_8: // 1 byte per pixel
return pixels;
case ARGB_4444: // 2 bytes per pixel, but depreciated
return pixels*2;
case ARGB_8888: // 4 bytes per pixel
return pixels*4;
case RGB_565: // 2 bytes per pixel
return pixels*2;
default:
return pixels;
}
}
然后您查询应用程序正在使用多少内存以及可用内存量,可能会占用一半并尝试将总图像缓存大小保持在该值之下,只需在您出现时从列表中删除(取消引用)旧图像违反此限制,不回收。当位图从缓存中取消引用并且没有被任何视图使用时,让垃圾收集器清理位图。
/**
* Calculates and adjusts the cache size based on amount of memory available and average file size
* @return
*/
synchronized private int calculateCacheSize(){
if(this.cachedBitmaps.size()>0){
long maxMemory = this.getMaxMemory(); // Total max VM memory minus runtime memory
long maxAllocation = (long) (ImageCache.MEMORY_FRACTION*maxMemory);
long avgSize = this.bitmapCacheAllocated / this.cachedBitmaps.size();
this.bitmapCacheSize = (int) (maxAllocation/avgSize);
}
return this.bitmapCacheSize;
}
我建议您不要使用recycle()
,它会导致很多间歇性异常(例如当看似已完成的视图尝试访问回收的位图时)并且通常看起来有问题。