Android--Handler的内存泄漏原因及解决方法

一、如何造成内存泄漏:

1、主线程的Looper对象会伴随该应用程序的整个生命周期

2、Java里,非静态内部类匿名类都会潜在引用它们所属的外部类

发送的延迟空消息(EmptyMessageDelayed)后、消息处理被前,该消息会一直保存在主线程的消息队列里持续时间,在持续时间里,该消息内部持有对handler的引用,由于handler属于非静态内部类,所以又持有对其外部类(即MainActivity实例)的潜在引用,引用关系如下图


条引用关系会一直保持直到消息得到处理,从而,这阻止了MainActivity被垃圾回收器(GC)回收,同时造成应用程序的内存泄漏,如下图:


二、解决方法

1、使用静态内部类+弱引用

在Java里,非静态内部类匿名类都会潜在的引用它们所属的外部类。 但是,静态内部类不会。所以,避免内存泄漏的解决方案是:只需要将Handler的子类设置成静态内部类;同时,还可以加上 使用WeakReference弱引用持有Activity实例。

原因:弱引用的对象拥有短暂的生命周期。在垃圾回收器线程扫描时,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。

public class MainActivity extends AppCompatActivity {


//将Handler改成静态内部类
     private static class FHandler extends Handler{
      //定义弱引用实例
      private WeakReference reference; 

      //在构造方法中传入需要持有的Activity实例
      public MyHandler(Activity activity) { 
      reference = new WeakReference(activity); }

        //通过复写handlerMessage()从而决定如何进行更新UI操作
        @Override
        public void handleMessage(Message msg) {
        //省略代码
            }
}

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    //主线程创建时便自动创建Looper和对应的MessageQueue,之前执行Loop()进入消息循环
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    //实例化Handler的子类
    //这里并无指定Looper,即自动绑定当前线程(主线程)的Looper和MessageQueue
        private final Handler showhandler = new FHandler();

         //启动子线程
        new Thread(){
            @Override
            public void run() {
                super.run();
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                 showhandler.sendEmptyMessageDelayed(0x1,10000);

                }
            }
        }.start();
    }

2、 当外部类结束生命周期时清空消息队列

内存泄漏的原因是: 当Activity结束生命周期时,Handler里的Message可能还没处理完,从而导致一系列的引用关系。其实,我们只要在当Activity结束生命周期时清除掉消息队列(MessageQueue)里的所有Message,那么这一系列引用关系就不会存在,就能防止内存泄漏。

解决方案:当Activity结束生命周期时(调用onDestroy()方法),同时清除消息队列里的所有回调消息(调用removeCallbacksAndMessages(null))。

@Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
    }



你可能感兴趣的:(Android,Android开发)