2014-02-20 72 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; 
    } 
}