Handler内存泄漏

Handler内存泄漏

  1. 关于Handler内存泄漏及解决办法:
    • 缘由:java

      1. handler会持有activity的匿名引用 (由于内部类的缘由,具体参考内部类实现),当activity要被回收时,由于handler在作耗时操做而没有被释放,从而内存泄漏
      2. 实例化Handler对象后,它就会主动与主线程的Looper的消息队列关联起来,全部发送到消息队列的Message都会拥有一个对Handler的引用,因此才由Looper处理消息时的回调Handler.handlerMessage(Message)来处理消息
    • public class SampleActivity extends Activity {
          private Handler mHandler = new Handler() {
              @Override
              public void handleMessage(Message msg) {
                  //...
              }
          }
      }
      复制代码
    • 解决办法:git

      • 将Handler设置为静态内部类(具体参考静态内部类和内部类区别),并使使Handler持有对Activity的弱引用github

        public class SampleActivity extends Activity {
                 .......
              private static class MyHandler extends Handler {
                     private final WeakReference<SampleActivity> mActivity;
                     public MyHandler(SampleActivity activity) {
                         myActivity = new WeakReference<SampleActivity>(activity);
                     }
        	 		@Override
         	 		public void handleMessage(Message msg) {
         	 			SampleActivity activity = mActivity.get();
             			if (activity != null) {
         			...
        	 		}
              }
           }
        }
        复制代码
      • 在activity生命周期onDestroy()中调用Handler.removeCallback()方法bash

        // 清空消息队列,移除对外部类的引用
        @Override
        protected void onDestroy() {
            super.onDestroy();
            mHandler.removeCallbacksAndMessages(null);
        
        }
        //Handler源码中removeCallbacksAndMessages()注释含义
        /**
         * Remove any pending posts of callbacks and sent messages whose
         * <var>obj</var> is <var>token</var>.  If <var>token</var> is null,
         * all callbacks and messages will be removed.
         */
        public final void removeCallbacksAndMessages(Object token) {
            mQueue.removeCallbacksAndMessages(this, token);
        }
        复制代码
      复制代码

内部类实现

  1. 内部类和静态内部类以及匿名内部类的应用
    • 内部类的优点:ide

      • 内部类方法能够访问盖内定义所在做用域的数据,包括私有数据函数

      • 内部类能够对同一个包中其余类隐藏oop

      • 想定义一个回调函数并且不像编写大量代码时,使用匿名内部类比较简洁post

    • 原理:this

      • 内部类的对象总有一个隐式引用,它指向了建立它的外部类对象spa

      • 编译器修改了全部内部类的构造器,添加了一个外围类的引用参数:

        public class Outer {
            ...
        class Inner {
            ...
            //Outer为外部类,Inner为内部类
            Outer out;
            public Inner(Outer outer) {
            out = outer;
        	}
        }
        }
        复制代码
    • 静态内部类: 使用内部类只是为了把一个类隐藏在另外一个类的内部,并不须要内部类引用外围类的对象。 所以能够将内部类声明为static,以便取消产生的引用

参考: juejin.im/post/5ccaa9…

github.com/francistao/…

相关文章
相关标签/搜索