在第一篇中我們討論到的方式是手動釋放記憶體
在這邊我們試著用另一種方式處理
首先要先大概介紹一下本次要使用的物件及相關的家人
StrongReference(強引用)
SoftReference(軟引用)
WeakReference(弱引用)
PhantomReference(虛引用)
基本上我們平常宣告物件的方式就是一種強引用(new Object()這類的寫法),既然如此那為何還硬要定義一個強引用的物件
我自己猜想,或許想用的某些物件會因為受到生命週期的影響而被回收,所以把他刻意放到強引用中或許就能降低它被回收的風險(純屬猜測)
被放到軟引用內的物件,會在記憶體不足的時候被回收,所以大概滿適合用來放一些,會很常被使用但沒有也不會太嚴重的資料。舉個例子,例如APP背景圖片,可能到每個頁面都會用到,但是不顯示說實在不會太影響APP功能使用
當Garbage Collection啟動時,不論記憶體是否充足,都有可能回收到弱引用存取的參數(被回收機率比軟引用大),至於這個"可能回收"的狀況是怎麼發生的,我猜想規則可能也是用LRU的方式吧
這名字聽起來就真的夠虛了,實際使用狀況也確實很虛,自己實測了一下發現不管什麼狀況都是null,馬上看一下Google官方Document,看完後覺得一陣尷尬,所以我說這東西到底要用在哪還真的沒概念
到這邊就介紹完本次會使用來處理Memory Leak的物件了
馬上來測試有沒有用,跟上一篇用一樣的寫法,這是我們把Context放到WeakReference中,同樣離開APP
本次測試leakcanary就沒有偵測到Memory Leak的狀況(使用SoftReference也可以達到一樣的效果)
可以看到下圖撰寫方式有點奇怪,主要是想測試手動呼叫GC是否能把WeakReference回收掉(很明顯的是不行XD)
其實還有做一個更極端的測試,在兩個Log中間插入多次的Bitmap decode動作把記憶體逼到極限,再試試看GC之後WeakReference是否還活著。這邊使用的test2圖片實際檔案約3MB,在手機上測試有時候再多讀取一張就會Crash,但呼叫GC後仍然沒有把WeakReference回收
使用這種Reference類的方法,確實可以避免掉Memory Leak問題,但實際資料被回收的時機就完全是交給系統了
各位大大如果有更好的測試方式歡迎分享討論