圖片加載<第四篇>:學會使用軟引用解決OOM問題

學會使用軟引用和弱引用可以進一步優化內存泄漏問題。

本文主要讓大家瞭解什麼叫強引用軟引用弱引用虛引用以及怎麼使用。

(1)強引用(StrongReference)
Object object = new Object();
String name= "zhangsan";

強引用在項目中很常見,程序猿已經習慣性的使用強引用了,以上兩句簡單代碼就是所謂的強引用。

當強引用對象佔用的內存超過最大可分配內存時,就是發生OOM。

(2)軟引用(SoftReference)

軟引用是用來描述一些有用但並不是必需的對象,在Java中用java.lang.ref.SoftReference類來表示。對於軟引用關聯着的對象,只有在內存不足的時候JVM纔會回收該對象。因此,這一點可以很好地用來解決OOM的問題,並且這個特性很適合用來實現緩存:比如網頁緩存、圖片緩存等。

SoftReference<String> str1 = new SoftReference<>(new String("hello1"));
Log.d("aaa", "str:"+str1.get());

//可以將軟引用存入引用隊列
ReferenceQueue<String> referenceQueue = new ReferenceQueue<>();
SoftReference<String> str2 = new SoftReference<>(new String("hello2"), referenceQueue);
Log.d("aaa", "str:"+str2.get());
(3)弱引用(WeakReference)

弱引用也是用來描述非必需對象的,當JVM進行垃圾回收時,無論內存是否充足,都會回收被弱引用關聯的對象。在java中,用java.lang.ref.WeakReference類來表示。

WeakReference<String> str = new WeakReference<>(new String("hello"));
Log.d("aaa", "str:"+str.get());
System.gc();
Log.d("aaa", "str:"+str.get());

結果爲:

(4)虛引用(PhantomReference)

虛引用和前面的軟引用、弱引用不同,它並不影響對象的生命週期。在java中用java.lang.ref.PhantomReference類表示。如果一個對象與虛引用關聯,則跟沒有引用與之關聯一樣,在任何時候都可能被垃圾回收器回收。

要注意的是,虛引用必須和引用隊列關聯使用,當垃圾回收器準備回收一個對象時,如果發現它還有虛引用,就會把這個虛引用加入到與之 關聯的引用隊列中。程序可以通過判斷引用隊列中是否已經加入了虛引用,來了解被引用的對象是否將要被垃圾回收。如果程序發現某個虛引用已經被加入到引用隊列,那麼就可以在所引用的對象的內存被回收之前採取必要的行動。

ReferenceQueue<String> queue = new ReferenceQueue<>();
PhantomReference<String> str = new PhantomReference<>(new String("hello"), queue);
Log.d("aaa", "str:"+str.get());

結果是:

(5)如何使用軟引用解決OOM問題

BitmapFactory.decodeFile()將圖片轉成bitmap,這句代碼是非常消耗性能的,爲了防止同一張圖片頻繁的轉成bitmap,我們需要將bitmap存入緩存,代碼如下:

private Map<String, Bitmap> bitmaps = new HashMap();

/**
 * 將Bitmap保存到緩存
 * @param path 文件路徑
 * @param bitmap 文件的bitmap對象
 */
private void addBitmapToCache(String path, Bitmap bitmap){
    bitmaps.put(path, bitmap);
}

/**
 * 獲取緩存中的bitmap
 * @param path
 * @return
 */
private Bitmap getBitmap(String path){
    Bitmap bitmap = bitmaps.get(path);
    return bitmap;
}

這個想法不錯,但是bitmap是非常佔用內存的,如果緩存容器中存放多個bitmap對象很有可能造成OOM問題,解決OOM問題需要引用軟引用或者弱引用軟引用只有在內存不足的時候JVM纔會回收該對象,弱引用無論內存是否充足,JVM進行垃圾回收時,都會回收被關聯的對象。這裏採用軟引用較爲適合。

private Map<String, SoftReference<Bitmap>> bitmaps = new HashMap();

/**
 * 將Bitmap保存到緩存
 * @param path 文件路徑
 * @param bitmap 文件的bitmap對象
 */
private void addBitmapToCache(String path, Bitmap bitmap){
    bitmaps.put(path, new SoftReference<Bitmap>(bitmap));
}

/**
 * 獲取緩存中的bitmap
 * @param path
 * @return
 */
private Bitmap getBitmap(String path){

    //獲取軟引用
    SoftReference<Bitmap> softReference = bitmaps.get(path);

    if(softReference == null){
        return null;
    }

    Bitmap bitmap = softReference.get();
    return bitmap;
}

以上代碼是一個不錯的方案,當獲取的bitmap爲null時,就重新在本地解碼圖片。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章