Handler内存泄漏

Handler内存泄漏

  1. 关于Handler内存泄漏及解决办法:
    • 原因:

      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) {
                  //...
              }
          }
      }
      复制代码
    • 解决办法:

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

         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()方法

        
        // 清空消息队列,移除对外部类的引用
        @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. 内部类和静态内部类以及匿名内部类的应用
    • 内部类的优势:

      • 内部类方法可以访问盖内定义所在作用域的数据,包括私有数据

      • 内部类可以对同一个包中其他类隐藏

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

    • 原理:

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

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

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

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

github.com/francistao/…

转载于:https://juejin.im/post/5ce7f7d6e51d4510a5033538

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值