美文网首页问题研究
自定义 Handler 时如何有效地避免内存泄漏问题?

自定义 Handler 时如何有效地避免内存泄漏问题?

作者: Joseph_L | 来源:发表于2019-11-15 17:58 被阅读0次

    一般情况下,我们说到 Handler 内存泄漏,指的是 Handler 泄漏掉了所在的 Activity。

    class MyActivity extends Activity{
        public Handler handler = new Handler(){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);    
        }   
    }
    

    上面的代码就有可能导致内存泄漏。代码中的 Handler 使用了 MyActivity 内部类的写法,在 Java 中,非静态内部类和匿名内部类都会隐式的持有一个外部类的引用。所以,这个 Handler 就持有了 Activity 的引用。

    由于 Handler 的特性问题,接下来有可能遇到几个问题。

    1. 用户关掉了 Activity,但是还有延迟消息没有发出或者发出去的消息还没被执行,由于 MessageQueue 持有这个 Message 的引用,Message 持有 Handler 的引用, Handler 又持有 Activity 的引用,这就导致这个已经关闭的 Activity 迟迟不能被内存回收;

    2. Handler 发出的消息在执行耗时任务,无法回收;

    问题有了,只需要给出对应的解决办法就好了。

    1. Handler 经常被用来发延时消息,我们需要保证 Activity 被 finish() 的时候,该线程的消息队列中没有这个 Handler 发出的消息。一个补救的办法就是在该类需要回收的时候,手动地把消息队列中的消息清空:mHandler.removeCallbacksAndMessages(null);

    2. 不让 Handler 持有 Activity 的实例,可以让该Handler成为静态内部类,因为静态内部类是不持有外部类的实例的;同时弱引用外部 Activity。

      public class MyActivity extends Activity {
      private static class MyHandler extends Handler {
        private final WeakReference<ShanActivity> mActivity;
      
        public MyHandler(Activity activity) {
          mActivity = new WeakReference<Activity>(activity);
        }
      
        @Override
        public void handleMessage(Message msg) {
          Activity activity = mActivity.get();
          if (activity != null) {}
        }
      }
      
      private MyHandler mHandler = new MyHandler();
      
      @Override
      protected void onDestroy() {
        mHandler.removeCallbacksAndMessages(null);
      }
      }
      
    3. 将 Handler 放到抽取出来放入一个单独的顶层类文件中,弱引用目标 Activity。

      public class WeakRefHandler extends Handler {
          private WeakReference<Callback> mWeakReference;
          
          public WeakRefHandler(Callback callback) {
              mWeakReference = new WeakReference<Handler.Callback>(callback);
          }
          
          public WeakRefHandler(Callback callback, Looper looper) {
              super(looper);
              mWeakReference = new WeakReference<Handler.Callback>(callback);
          }
          
          @Override
          public void handleMessage(Message msg) {
              if (mWeakReference != null && mWeakReference.get() != null) {
                  Callback callback = mWeakReference.get();
                  callback.handleMessage(msg);
              }
          }
      }
      

    相关文章

      网友评论

        本文标题:自定义 Handler 时如何有效地避免内存泄漏问题?

        本文链接:https://www.haomeiwen.com/subject/ecisictx.html