歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

【Google官方教程】第三課:緩存Bitmap

譯者按: 在Google最新的文檔中,提供了一系列含金量相當高的教程。因為種種原因而鮮為人知,真是可惜!Ryan將會細心整理,將之翻譯成中文,希望對開發者有所幫助。

本系列是Google關於展示大Bitmap(位圖)的官方演示,可以有效的解決內存限制,更加有效的加載並顯示圖片,同時避免讓人頭疼的OOM(Out Of Memory)。

【Google官方教程】系列相關閱讀: http://www.linuxidc.com/search.aspx?where=nkey&keyword=14914

-------------------------------------------------------------------------------------

譯文:

加載一個Bitmap(位圖)到你的UI界面是非常簡單的,但是如果你要一次加載一大批,事情就變得復雜多了。在大多數的情況下(如ListView、GridView或者ViewPager這樣的組件),屏幕上的圖片以及馬上要在滾動到屏幕上顯示的圖片的總量,在本質上是不受限制的。

像這樣的組件在子視圖移出屏幕後會進行視圖回收,內存使用仍被保留。但假設你不保留任何長期存活的引用,垃圾回收器也會釋放你所加載的Bitmap。這自然再好不過了,但是為了保持流暢且快速加載的UI,你要避免繼續在圖片回到屏幕上的時候重新處理。使用內存和硬盤緩存通常能解決這個問題,使用緩存允許組件快速加載並處理圖片。

這節課將帶你使用內存和硬盤緩存Bitmap,以在加載多個Bitmap的時候提升UI的響應性和流暢性。

使用內存緩存

以犧牲寶貴的應用內存為代價,內存緩存提供了快速的Bitmap訪問方式。LruCache類(可以在Support Library中獲取並支持到API  Level 4以上,即1.6版本以上)是非常適合用作緩存Bitmap任務的,它將最近被引用到的對象存儲在一個強引用的LinkedHashMap中,並且在緩存超過了指定大小之後將最近不常使用的對象釋放掉。

注意:以前有一個非常流行的內存緩存實現是SoftReference(軟引用)或者WeakReference(弱引用)的Bitmap緩存方案,然而現在已經不推薦使用了。自Android2.3版本(API Level 9)開始,垃圾回收器更著重於對軟/弱引用的回收,這使得上述的方案相當無效。此外,Android 3.0(API Level 11)之前的版本中,Bitmap的備份數據直接存儲在本地內存中並以一種不可預測的方式從內存中釋放,很可能短暫性的引起程序超出內存限制而崩潰。

為了給LruCache選擇一個合適的大小,要考慮到很多原因,例如:

• 其他的Activity(活動)和(或)程序都是很耗費內存的嗎?

• 屏幕上一次會顯示多少圖片?有多少圖片將在屏幕上顯示?

• 設備的屏幕大小和密度是多少?一個超高清屏幕(xhdpi)的設備如Galaxy Nexus,相比Nexus S(hdpi)來說,緩存同樣數量的圖片需要更大的緩存空間。

• Bitmap的尺寸、配置以及每張圖片需要占用多少內存?

• 圖片的訪問是否頻繁?有些會比其他的更加被頻繁的訪問到嗎?如果是這樣,也許你需要將某些圖片一直保留在內存中,甚至需要多個LruCache對象分配給不同組的Bitmap。

• 你能平衡圖片的質量和數量麼?有的時候存儲大量低質量的圖片更加有用,然後可以在後台任務中加載另一個高質量版本的圖片。

對於設置緩存大小,並沒有適用於所有應用的規范,它取決於你在內存使用分析後給出的合適的解決方案。緩存空間太小並無益處,反而會引起額外的開銷,而太大了又可能再次引起java.lang.OutOfMemory異常或只留下很小的空間給應用的其他程序運行。

這裡有一個設置Bitmap的LruCache示例:

private LruCache<String, Bitmap> mMemoryCache;

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    // Get memory class of this device, exceeding this amount will throw an
    // OutOfMemory exception.
    final int memClass = ((ActivityManager) context.getSystemService(
            Context.ACTIVITY_SERVICE)).getMemoryClass();

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

    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
        @Override
        protected int sizeOf(String key, Bitmap bitmap) {
            // The cache size will be measured in bytes rather than number of items.
            return bitmap.getByteCount();
        }
    };
    ...
}

public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
    if (getBitmapFromMemCache(key) == null) {
        mMemoryCache.put(key, bitmap);
    }
}

public Bitmap getBitmapFromMemCache(String key) {
    return mMemoryCache.get(key);
}

Copyright © Linux教程網 All Rights Reserved