WeakRefrence Demo

Strong reference(强引用)

在Java中,非静态内部类会在其整个生命周期中持有对它外部类的强引用。

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new MyAsyncTask(this).execute();
    }

    private class MyAsyncTask extends AsyncTask { 

        @Override
        protected Object doInBackground(Object[] params) {

            // 模拟耗时任务
            try {
                Thread.sleep(60000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            return doSomeStuff();
        }
        private Object doSomeStuff() {
            return new Object();
        }
        @Override
        protected void onPostExecute(Object object) {
            super.onPostExecute(object);
            // 更新UI
        }
    }
}

这段代码里,MyAsyncTask会跟随Activity的onCreate去创建并开始执行一个长时间的耗时任务,并在耗时任务完成后去更新MainActivity中的UI。这是一个很常见的使用场景,却会导致内存泄露问题。

MainActivity被销毁时,MyAsyncTask中的耗时任务可能仍没有执行完成,所以MyAsyncTask会一直存活。此时,由于MyAsyncTask持有着其外部类,即MainActivity的引用,将导致MainActivity不能被垃圾回收。如果MainActivity中还持有着Bitmap等大对象,反复进出这个页面几次可能就会出现OOM Crash了。

WeakReference(弱引用)

弱引用通过类WeakReference来表示。弱引用并不能阻止垃圾回收。如果使用一个强引用的话,只要该引用存在,那么被引用的对象是不能被回收的。弱引用则没有这个问题。在垃圾回收器运行的时候,如果对一个对象的所有引用都是弱引用的话,该对象会被回收。

我们调整一下上面例子中的代码,使用弱引用去避免内存泄露:

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new MyAsyncTask(this).execute();
    }

    private static class MyAsyncTask extends AsyncTask {
        private WeakReference<MainActivity> mainActivity;    

        public MyAsyncTask(MainActivity mainActivity) {   
            this.mainActivity = new WeakReference<>(mainActivity);            
        }
        @Override
        protected Object doInBackground(Object[] params) {

            // 模拟耗时任务
            try {
                Thread.sleep(30000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return doSomeStuff();
        }
        private Object doSomeStuff() {
            //do something to get result
            return new Object();
        }
        @Override
        protected void onPostExecute(Object object) {
            super.onPostExecute(object);
            if (mainActivity.get() != null){
                // 更新UI
            }
        }
    }
}

大家可以注意到,主要的不同点在于,我们把MyAsyncTask改为了静态内部类,并且其对外部类MainActivity的引用换成了:

private WeakReference<MainActivity> mainActivity;

当MainActivity destroy的时候,由于MyAsyncTask是通过弱引用的方式持有MainActivity,所以并不会阻止MainActivity被垃圾回收器回收,也就不会有内存泄露产生了。

I Don't Want Your Money, I Want Aragaki Yui.