Weak reference、Soft reference 可以用來解決 Memory leak 的問題,當我們用 Weak reference 指向某個物件,GC 在回收時,就會將其回收掉。而 Soft reference 與 Weak reference 的差異在於,被 Soft reference 所參考的物件,要等到記憶體不足時,才會將其回收掉。
不過大部分的情況下,直接使用 Weak reference 可能不是個最佳解法,接著我們也將一一說明。我們在 Memory leak 篇用 Static property 範例來介紹怎麼用 Weak reference 解決 Memory leak。如下程式碼的WeakReference<TextView>
,在 TextView 前面加上 WeakReference 代表弱引用就可以解決 Memory leak 的問題。
class MainActivity : AppCompatActivity() { companion object {
//加上WeakReference避免 Memory leak
private var textView: WeakReference<TextView>? = null
} override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main7) //加上WeakReference
textView = WeakReference(findViewById(R.id.textView))
}
}
但最大的問題其實還是 textView
本來就不應該被放到 static property 的,我們應該檢視的是把 TextView 放到了static property。
接著另一個範例,同樣是用 WeakReference 來解決在 Handler 裡參考了 Activity 的問題。
internal class MyHandler(activity: Activity) : Handler() {
var activityReference: WeakReference<Activity>
init {
activityReference = WeakReference(activity)
}
override fun handleMessage(msg: Message) {
super.handleMessage(msg)
val activity = activityReference.get()
if (activity != null) {
}
}
}
這個範例用了 WeakReference 解決 Memory leak,卻也反應了更明顯的架構問題。例如:
- 非同步處理應使用 RxJava 或 Coroutine。
- 應使用 MVVM、MVP 等 的架構做為邏輯處理與資料更新的溝通方式。
- Activity 裡不應該有邏輯等等。
最後,Weak reference 可以用來解決 Memory leak 的問題,但在使用 Weak Reference 之前,請先確認真正造成 Memory leak 的原因是什麼?是否有更好的解決方式來避免 Memory leak。
參考:
https://medium.com/google-developer-experts/weakreference-in-android-dd1e66b9be9d
https://medium.com/google-developer-experts/finally-understanding-how-references-work-in-android-and-java-26a0d9c92f83