android handler内存泄露及解决方案

sancaiodm Android 2021-12-15 1293 0

在java中,非静态的内部类和匿名内部类都会隐式的持有一个外部类的引用。静态内部类则不会持有外部类的引用。

那我们先看下面这段代码:

private Handler odmHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {

    }
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //使用odmHandler执行延迟任务runnable.
    //使用odmHandler.sendEmptyMessageDelayed()执行延迟任务,
    odmHandler.postDelayed(new Runnable() {
        @Override
        public void run() {

        }
    }, 5000);
    finish();
}

     如上代码,在oncreate方法的最后,我们直接finsh了当前的activity,原则上则activity是要被销毁的,但因为我们odmHandler是被delay的Message持有了引用的,如果外部类是Activity,odmHandler又隐式的持有外部类(Activity)的引用,此时延时的message还未及时被处理,就finsh()了,或是按返回键退出销毁了Activity,那么就会引起Activity泄露 。因为原本应该finish()的activity无法被GC正常内存回收,

static class MyHandler extends Handler{
        private final WeakReference<Activity> mWeakReference;
        public MyHandler(Activity activity) 
        {
            mWeakReference=new WeakReference<Activity>(activity);
        }
        @Override
        public void handleMessage(Message msg)
        {
            final Activity activity= mWeakReference.get();
            if(activity!=null)
            {
                if (msg.what == 1)
                {
                    activity.xxx();
                }
            }
        }
    }

再加在Activity的onDestroy()方法中加这句:

@Override
public void onDestroy() {
   // 移除所有消息
   handler.removeCallbacksAndMessages(null);
   // 或者移除单条消息
   handler.removeMessages(what);
}


评论