Bootstrap

匿名内部类造成的内存泄漏

" ——————test1
        new AsyncTask< void , void = "" >() {
            @Override
            protected Void doInBackground(Void... params) {
                SystemClock.sleep( 10000 );
                return null ;
            }
        }.execute();
——————test2
        new Thread( new Runnable() {
            @Override
            public void run() {
                SystemClock.sleep( 10000 );
            }
        }).start();
上面的异步任务和Runnable都是一个匿名内部类,因此它们对当前Activity都有一个隐式引用。如果Activity在销毁之前,任务还未完成,
那么将导致Activity的内存资源无法回收,造成内存泄漏。正确的做法还是使用静态内部类的方式,如下:
static class MyAsyncTask extends AsyncTask<void, void=""> {
        private WeakReference<context> weakReference;
        public MyAsyncTask(Context context) {
            weakReference = new WeakReference<>(context);
        }
        @Override
        protected Void doInBackground(Void... params) {
            SystemClock.sleep( 10000 );
            return null ;
        }
        @Override
        protected void onPostExecute(Void aVoid) {
            super .onPostExecute(aVoid);
            MainActivity activity = (MainActivity) weakReference.get();
            if (activity != null ) {
                //...
            }
        }
    }
    static class MyRunnable implements Runnable{
        @Override
        public void run() {
            SystemClock.sleep( 10000 );
        }
    }
//——————
    new Thread( new MyRunnable()).start();
    new MyAsyncTask( this ).execute();
这样就避免了Activity的内存资源泄漏,当然在Activity销毁时候也应该取消相应的任务AsyncTask::cancel(),避免任务在后台执行浪费资源。

一些建议

1、对于生命周期比Activity长的对象如果需要应该使用ApplicationContext
2、在涉及到Context时先考虑ApplicationContext,当然它并不是万能的,对于有些地方则必须使用Activity的Context

3、对于需要在静态内部类中使用非静态外部成员变量(如:Context、View ),可以在静态内部类中使用弱引用来引用外部类的变量来避免内存泄漏
4、对于生命周期比Activity长的内部类对象,并且内部类中使用了外部类的成员变量,可以这样做避免内存泄漏:
将内部类改为静态内部类 静态内部类中使用弱引用来引用外部类的成员变量

5、对于不再需要使用的对象,显示的将其赋值为null,比如使用完Bitmap后先调用recycle(),再赋为null
6、保持对对象生命周期的敏感,特别注意单例、静态对象、全局性集合等的生命周期

;