美文网首页
Handler的不完全解析

Handler的不完全解析

作者: 慕尼黑凌晨四点 | 来源:发表于2020-10-27 15:16 被阅读0次

    Handler是什么

    • 个人理解:Handler是进程间进行通信的一种方式。

    • 官方:

      A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler it is bound to a Looper. It will deliver messages and runnables to that Looper's message queue and execute them on that Looper's thread.

      Handler允许你发送Message并处理Runnable对象,通过MessageQueue的关联。每个Handler实例和线程,和线程的MessageQueue相关联。当你创建Handler的时候他会绑定到Looper。他会将message和runnables交付到Looper的message列队中,并在Looper线程中执行他(runnables)。

      There are two main uses for a Handler: (1) to schedule messages and runnables to be executed at some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.

      主要两个作用:1.在未来某个时刻执行任务;2.在不同的线程中入队并执行相关操作。

    Handler机制和原理

    图解Handler运行机制

    大致流程如图,首先初始化一个Handle(callback),后调用sendMsg(msg)方法【post方法最后也是调用的sendMsg()】,传入Message对象,将这个handle赋值给msg.target。然后调用queue.enqueueMessage(msg)将message入队。

    另一方面,另外一个线程(通常为主线程)会调用Looper.loop()方法循环从Message Queue中读取数据【此方法在ActivityThread类中已被调用,所以主线程不用再次调用;若为其他线程则需要自己手动调用一次了】。获取到数据后调用msg.target.dispatchMessage(msg);方法。target就是handler,这里就跳回到了Handle所在线程中来。

        public void dispatchMessage(@NonNull Message msg) {
            if (msg.callback != null) {
                handleCallback(msg);
            } else {
                if (mCallback != null) {
                    if (mCallback.handleMessage(msg)) {
                        return;
                    }
                }
                handleMessage(msg);
            }
        }
    

    Handler 在处理消息时会先查看 Message 是否有 callback,有则优先交由 Message 的 callback 处理消息,没有的话再去看看Handler 有没有 callback,如果也没有才会交由 handleMessage() 这个方法执行

    实现了线程的切换

    这里Handle和Lopper一定在一个线程,因为初始化handle之前必须要执行Looper.prepare()方法,【因为handle中要持有Looper对象,因为messageQueue是从Looper对象中获取到的】。

    之所以我们平常没写Looper.prepare()也能运行,是因为ActivityThread中已经调用了该方法。

    Handler是怎么切换线程的

    上面:point_up:已经写了。看了上文还不懂可能我表达出了问题。

    Handler内存泄露的原因?

    直接在MainActivity中匿名内部类 new Handle(){} 或者创建非静态内部类的时候会有warning警告。

    • 匿名内部类
    image-20201027122230172.png
    • 非静态内部类:
    image-20201027122340874.png

    且给出了建议,加上static,改为静态内部类。

    原因是:1. 非静态内部类(或匿名内部类)【Handler】会一直持有外部类(这里的MainActivity)的引用。

    1. MessageQueue存储了Message,而Messagetarget属性为handler对象,handler又持有的Activity的对象。
    2. 所以,当Activiy要销毁的时候,MessageQueue中还存在未处理完的Message,leaks...

    怎么处理handler的内存泄露;

    1.静态内部类 + 弱引用

    也就是上图中Android studio 建议的方案。

    同时,加上WeakReference弱引用持有Activity实例,GC回收时发现了这个弱引用对象便会将其回收,从而避免内存泄露。

    详细代码参考Android 内存泄露:详解 Handler 内存泄露的原因

    2 .当外部类结束生命周期时,清理Handle或Looper

    • 清空Handle
    @Override
        protected void onDestroy() {
            super.onDestroy();
            mHandler.removeCallbacksAndMessages(null);
            // 外部类Activity生命周期结束时,同时清空消息队列 & 结束Handler生命周期
        }
    
    • 结束Looper
    @Override
    protected void onDestroy() {
        super.onDestroy();
        getMainLooper().quitSafely();
    }
    

    Looper死循环为什么不会导致应用卡死?

    Android应用程序的主线程在进入消息循环过程前,会在创建一个新binder线程。

    public static void main(String[] args) {
        .....
        //创建Looper和MessageQueue对象,用于处理主线程的消息...
        Looper.prepareMainLooper();
        
        //创建ActivityThread对象
        ActivityThread thread = new ActivityThread();
        
        //建立Binder通道 (创建新线程)
        thread.attach(false, startSeq);
        
         //消息循环运行
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
    

    app一直开着,Looper.loop就会一直循环【就是为了保障app的运行啊】,由于有Binder线程的存在,所以Looper中会收到Message,当收到不同的Message时就会采取不同的措施:

    ActivityThread中的handleMessage方法

    包括所谓BIND_APPLICATION、LAUNCH_ACTIVITY等一系列方法,都是写在这里,通过接收到的消息不同,进行相应的操作。

    附上Activity创建流程图一张:

    Activity创建流程图

    参考 :

    知乎:https://www.zhihu.com/question/34652589

    简书:Android 内存泄露:详解 Handler 内存泄露的原因

    简书:Activity启动流程

    相关文章

    Handler 10问,你顶的住吗?

    相关文章

      网友评论

          本文标题:Handler的不完全解析

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