14.Android 控制Handler内存泄露 技巧

14.Android 控制Handler内存泄露 技巧


Handler 警告

In Android, Handler classes should be static or leaks might occur, Messages enqueued on the application thread’s MessageQueue also retain their target Handler. If the Handler is an inner class, its outer class will be retained as well. To avoid leaking the outer class, declare the Handler as a static nested class with a WeakReference to its outer class

这是在用Handler不加static都会出现的一个警告。


Handler 内存泄露缘由

  • 一个Android应用启动的后,都会创建一个主UI线程,再为这个主UI线程提供一个Looper对象,这样所有的Android框架的事件(Activity的生命周期方法调用和事件)都是放入消息中,再加入Looper处理的MessageQueue中。也就是说主线程的Looper生命周期是与Android应用一样长的。

  • 每次在Handler.sendMessage(message)的时候,实际已经发送的message已经包含了改Handler的引用。因为在只有这样Looper才能调用处理改message的handler,进而走到handler.handleMessage(Message msg)中,不然,你想,我发一个message,Looper怎么知道message处理过后告诉哪个Handler执行handler.handleMessage(Message msg)

  • 非静态的内部类和匿名的内部类都会隐式地持有了它的对应外部类的引用。静态的内部类不会持有外部类的引用。

出现泄漏的场景:假如我的Handler里做了很多耗时的工作,在Activity.finish()后Handler还在忙碌的话,就一直持有该Activity的引用,Activity无法回收,进行导致Activity持有的很多资源都无法回收,就会出现Handler的内存泄漏


解决思路

解决思路基本上是:不用非静态的Handler,继承Handler的时候,可以选择

  • 独立出一个Handler类
  • 静态Handler

以上,这两种方法。因为静态的内部类不会持有外部类(Activity)的引用,所以不会导致外部类实例的内存泄露。

在Android中很多的内存泄露都是由于在Activity中使用了非静态内部类导致的,所以使用时要非静态内部类时要格外注意,如果实例的持有对象的生命周期大于其外部类对象,那么就有可能导致内存泄露。


Handler 通用模板

    private TextView handlerTV;
    private static final int HANDLER_SUCCESS = 206;
    private static class RefreshHandler extends Handler {
        private final WeakReference<RefreshUIActivity> mActivity;

        public RefreshHandler(RefreshUIActivity activity) {
            mActivity = new WeakReference<>(activity);
        }

        /**
         * Subclasses must implement this to receive messages.
         *
         * @param msg
         */
        @Override
        public void handleMessage(Message msg) {
            RefreshUIActivity activity = this.mActivity.get();
            if (activity != null) {
                switch (msg.what) {
                    case HANDLER_SUCCESS: {
                        activity.handlerTV.setText("success");
                        break;
                    }
                }
            }
        }
    }


    private final RefreshHandler refreshHandler = new RefreshHandler(RefreshUIActivity.this);
    private final Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            Message message = RefreshUIActivity.this.refreshHandler.obtainMessage();
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            message.what = HANDLER_SUCCESS;
            refreshHandler.sendMessageDelayed(message, 2000);
        }
    };
    private final Thread mThread = new Thread(mRunnable);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值