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);
        }
    }
}