2016-09-16 224 views
0

在我的應用程序中,我有包含一些縮略圖的不同列表視圖。 今天我開始重構,我想實現LRU緩存。我遵循Android指南,但是我想知道是否最好只爲整個應用初始化一個LRU緩存,或者更好地爲每個列表視圖初始化LRU緩存。 我害怕outOfMemory。 因此,我有以下問題,我不能自己回答: - 單個模式初始化一個LRU緩存是一個好主意? - 如果內存不足,是否會導致outOfMemory情況出現以下LRU Cache的初始化?LRU緩存:僅爲整個應用初始化一個緩存?

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    ... 
    // Get max available VM memory, exceeding this amount will throw an 
    // OutOfMemory exception. Stored in kilobytes as LruCache takes an 
    // int in its constructor. 
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024); 

    // Use 1/8th of the available memory for this memory cache. 
    final int cacheSize = maxMemory/8; 

    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { 
     @Override 
     protected int sizeOf(String key, Bitmap bitmap) { 
      // The cache size will be measured in kilobytes rather than 
      // number of items. 
      return bitmap.getByteCount()/1024; 
     } 
    }; 
    ... 
} 
  • 如果內存不足時,LRU緩存自動釋放?我想知道當我使用LRU緩存(應用程序崩潰,因爲內存不足)時應用程序是否會釋放內存問題?

  • 只有一個LRU緩存可用於整個應用程序嗎?

  • 整個應用程序有多個LRU緩存,它們會成爲問題嗎?

回答

1

我有很多問題,所以我可以在這裏給你一些有用的答案。

如果內存不足,LRU緩存會自動釋放?我想知道如果,如果我用LRU緩存

的LRU緩存將不會自動釋放內存的應用程序將有問題來釋放內存。您需要以編程方式驅逐條目。

只有一個LRU緩存整個應用程序,它可以是一個問題?

整個應用程序有多個LRU緩存,它們會成爲問題嗎?

LruCache類是一個泛型類,其中包含鍵的類型和值的類型。我想說你想要爲每個要緩存的對象類型創建一個LRU緩存。你正在做我所做的事:緩存Bitmap s和鍵入String s。

只是旁註:小心使用bitmap.getByteCount()。 JavaDocs說:

從KITKAT開始,此方法的結果不能再用於確定位圖的內存使用情況。見getAllocationByteCount()

我正在使用LRU Cache作爲Bitmap s。我認爲只要調用此方法就可以覆蓋Application.onTrimMemory()並清除緩存。

此外,我做了同樣的事情,並根據應用程序可用的堆內存的一定百分比設置緩存大小。

但在這裏會發生什麼:當我的應用程序在內存不足的狀態,我的應用程序會嘗試下載與內存不足的圖像時,GC將運行,但BitmapFactory仍然無法爲Bitmap分配內存。日誌顯示onTrimMemory()方法異步調用,有時在投擲OutOfMemoryError後幾乎整整一秒!

HEY GOOGLE:如果系統不能告訴我,我的內存不足UNTIL OutOfMemoryError被拋出後,如何在地獄我應該怎麼管理我的記憶?

瘋狂。純粹,完全瘋狂。

下面是我最終做的事情:我會在嘗試塊中捕獲OutOfMemoryError,清除那裏的緩存,然後重試映像請求到服務器。他們告訴你不要做的確切事情。但它最終解決了我的問題。該應用現在更加穩定。

所以在你實現你的LRU緩存之後,確保你壓力測試你的應用程序;嘗試將其納入低內存環境並查看其行爲。對我來說,使用模擬器時效果最好。該模擬器將具有96M的小堆限制,但如果它具有高屏幕分辨率,則圖像資源將會變得非常大,這使得內存最大化變得相當容易。

如果要顯示縮略圖,但你從服務器獲取圖像,他們可能比你的大ImageView,請確保你閱讀這篇文章:Loading Large Bitmaps Efficiently | Android Developers學習如何下載一個適當大小的位圖,不浪費內存。

您也可以嘗試讓系統進行緩存並設置HttpResponseCache

無論你最終做什麼,一定要強調你的應用程序,並看看它沒有太多的堆剩餘時的行爲。

並準備處理一點挫敗感。

+0

嗨!此時我正在初始化listview構造函數中的weakHashMap,並將縮略圖放在該地圖中。我當時認爲最好使用LRU緩存,但在閱讀你的答案後,我有點害怕。 – aeroxr1

+1

我剛纔看了一下'WeakHashMap'。我沒有意識到這是*鍵*在該類中具有弱引用,而不是值。出於這個原因,我想你可能想要像'Map >'這樣的地圖。我現在有點希望,我已經這樣做了。由於'LruCache'類與GC沒有任何隱含關係,因此幾乎沒有用處。所以你可能走在正確的軌道上。只要測試它的廢話,如果它的行爲可以接受,宣佈勝利,並稱它爲一天。 –

+0

在弱哈希圖是弱關鍵的參考?真的嗎?我不知道這個! – aeroxr1