Java雖然有垃圾回收,但是仍然存在內存泄露,比如靜態變量、緩存或其他長生命周期的對象引用了其他對象,這些被引用的對象就會長期不能被GC釋放,導致內存泄露。
弱引用(WeakReference)是解決這個問題的一種廉價方案,它不會阻止所引用的對象被GC,在需要的時候能夠釋放出內存。也因為這樣,在每次訪問弱引用中的對象時,必須檢查對象是否為空(已被GC),算是一點點代價吧。
使用弱引用的幾個小心得:
1,使用生命周期匹配的強引用避免弱引用。比如緩存需要一個Context引用,緩存是長生命周期的,在程序運行過程中會一直存在,如果使用Activity作為Context,因為Activity隨時可能finish,生命周期與緩存不匹配,而如果使用Application作為Context,因為Application也是在程序運行中一直存在,周期是匹配的,就不會發生內存泄露,也就不需要弱引用。
2,配對引用和釋放引用避免弱引用。在Activity的onResume中注冊的回調可以在onPause的時候取消注冊,可以避免對Activity的長期引用。
3,只能對非關鍵的變量使用弱引用。還是上面這個緩存的例子,Context是加載緩存數據必須的變量。如果使用弱引用,加載緩存的時候可能因為Context被GC而失敗或者FC。
4,使用弱引用有時候也需要額外的清理。在一個緩存中,我們使用ArrayList保存了一些View的弱引用,這些View在不存在其他強引用的時候確實能夠被GC,但是ArrayList的大小未變,仍然包含這些View已被GC的弱引用,弱引用自身反倒導致了內存泄露。
public
class
ViewCallback {
private
WeakReference<View> mViewReference;
public
ViewCallback(View view) {
mViewReference =
new
WeakReference<View>(view);
}
public
void
show() {
View view = mViewReference.get()
if
(view !=
null
) {
view.setVisibility(View.VISIBLE);
}
}
}
