2014-02-20 53 views
2

我已经使用内存LRU缓存来缓存android应用程序中的位图。但是在一些位图加载到LRU地图后,app强制关闭,表示内存异常。我已经花了整整一天的时间,但还没有找到解决方案,请任何人都可以帮助我,我很困扰这个问题。提前感谢。如何防止LRU缓存中的内存不足错误android

这里是我的代码

final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024); 
final int cacheSize = maxMemory/8; 
bitmapHashMap = new LruCache<String, Bitmap>(cacheSize) 
{ 
@SuppressLint("NewApi") 
@Override 
protected int sizeOf(String key, Bitmap value) 
{ 
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB_MR2) 
{ 
return value.getByteCount()/1024; 
} 
else 
{ 
return (value.getRowBytes() * value.getHeight())/1024; 
} 
} 
}; 
+0

什么是cacheSize? – pskink

回答

0

你遵循这些指导? http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html 这是一个很好的教程,以了解如何实现位图存储。

+0

是的,我已经提到了内存缓存的相同文档,但它给我的内存不足错误。是因为图像没有被回收或者是什么?我是否需要手动回收lru map中的这些位图? – Ravi

+0

您必须将LRU Cache的用法与一组soffReference 结合使用。 SoftReference类将在自动删除位图实例之前发生内存不足异常。 – Substitut

2

如果应用程序使用的Android版本:largeheap =“真”,

切勿使用Runtime.getRuntime().maxMemory(),你很可能会更频繁地使用更多的内存比速效和OOM,而是使用存储类和计算缓存的大小如下:

/** Default proportion of available heap to use for the cache */ 
    final int DEFAULT_CACHE_SIZE_PROPORTION = 8; 

    ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 
    int memoryClass = manager.getMemoryClass(); 
    int memoryClassInKilobytes = memoryClass * 1024; 
    int cacheSize = memoryClassInKilobytes/DEFAULT_CACHE_SIZE_PROPORTION; 
    bitmapHashMap = new LruCache<String, Bitmap>(cacheSize) 
+1

我已经使用过相同的内容,但是它给出了相同的内存不足错误,是因为图像没有被回收或者是什么? Lru默认不执行这些回收事项? – Ravi

+0

DEFAULT_CACHE_SIZE_PROPORTION的值是什么,因为我无法找到对它的任何引用。 – Theo

+0

D'OH!..我会修复 – petey

1

Out of Memory Exception当位图超过可用的虚拟内存引起的,一个好的做法是位图的回收。

bitmap.recycle(); 

在这里阅读更多

When should I recycle a bitmap using LRUCache?

由马克·墨菲先生回答的问题。

+2

Lru不能执行这些回收的事情默认情况下自己或什么?在代码中手动执行这些回收是强制的吗? – Ravi

0

当你有异常时,你应该清除缓存并再次下载。当内存超过时,检查以下功能以清除缓存

private Bitmap getBitmap(String url) 
      { 
    File f=fileCache.getFile(url); 
    //from SD cache 
    Bitmap b = decodeFile(f); 
    if(b!=null) 
     return b; 

    //from web 
    try { 
     Bitmap bitmap=null; 
     // URL imageUrl = new URL(url); 

     /***/ 

     HttpURLConnection conn = null; 
     URL imageUrl = new URL(url); 
     if (imageUrl.getProtocol().toLowerCase().equals("https")) { 
      trustAllHosts(); 
      HttpsURLConnection https = (HttpsURLConnection) imageUrl.openConnection(); 
      https.setHostnameVerifier(DO_NOT_VERIFY); 
      conn = https; 
     } else { 
      conn = (HttpURLConnection) imageUrl.openConnection(); 
     } 
     /***/ 



     // HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection(); 
     conn.setConnectTimeout(30000); 
     conn.setReadTimeout(30000); 
     conn.setInstanceFollowRedirects(true); 
     InputStream is=conn.getInputStream(); 
     OutputStream os = new FileOutputStream(f); 
     Utils.CopyStream(is, os); 
     os.close(); 
     bitmap = decodeFile(f); 
     return bitmap; 
    } catch (Throwable ex){ 
     ex.printStackTrace(); 
     if(ex instanceof OutOfMemoryError) 
      memoryCache.clear(); 
     return null; 
    } 
}