美文网首页
Handler原理分析

Handler原理分析

作者: 我挺平凡 | 来源:发表于2019-07-22 19:08 被阅读0次

1、定义

一套 Android 消息传递机制

2、作用

在多线程的应用场景中,将工作线程中需更新 UI的操作信息 传递到UI主线程,从而实现 工作线程对UI的更新处理,最终实现异步消息的处理

3、意义

  • 问:为什么要用 Handler消息传递机制
  • 答:多个线程并发更新UI的同时 保证线程安全

4、 相关概念

Handler 、 Looper 、Message 、MessageQueue都与Android异步消息处理线程相关的概念.

那么和Handler 、 Looper 、Message、MessageQueue有啥关系?其实Looper负责的就是创建一个MessageQueue,然后进入一个无限循环体不断从该MessageQueue中读取消息,而消息的创建者就是一个或多个Handler 。
主线程创建一个handler对象后维护一个Looper,Looper创建一个MessageQueue,通过死循环一直检测MQ是否有消息进来,如果有通知handler处理消息,并且handler就是负责往MQ发消息的对象

5、 使用方式

  • Handler的使用方式因 发送消息到消息队列的方式不同而不同
  • 共分为2种:使用Handler.sendMessage()使用Handler.post()

6、 图解

image.png

7、 源码分析

1.new Handler()
        --->this(null, false); 
        --->Looper mLooper = Looper.myLooper();
        --->MessageQueue mQueue =  mLooper.mQueue

    
2.handler.sendMessage(message);
        --->sendMessageAtTime()
        --->enqueueMessage(queue, msg, uptimeMillis)
        --->msg.target = this;  ---  Handler对象
        --->queue.enqueueMessage(msg, uptimeMillis)  --  消息存到消息队列

3.Looper
    prepare():
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));

    
        new Looper():
            private Looper(boolean quitAllowed) {
                mQueue = new MessageQueue(quitAllowed);
                mThread = Thread.currentThread();
            }

        注意:一个线程中只能有一个Looper对象,只能有一个消息队列MessageQueue


    loop():

        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Loop  r; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            。。。。

            msg.target.dispatchMessage(msg);  ---  handler

        }
    
4.handler.dispatchMessage():
        if (msg.callback != null) {
            handleCallback(msg); --- >回调自身Runnable中run方法,使用post方法的时候
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg); --- >子类必须重写
        }

        
        回到最后处理的方法:
            private static void handleCallback(Message message) {
                message.callback.run();
            }
        
            /**
             * Subclasses must implement this to receive messages.
             */
            public void handleMessage(Message msg) {
            }

4、 总结

  1. Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。

  2. Handler的sendMessage方法,会给msg的target赋值为handler自身,然后将Message加入MessageQueue中。

  3. Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。

  4. Looper.loop()会让当前线程进入一个无限循环,从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。

  5. handler.dispatchMessage(msg)分发消息,如果是sendMessage(),会回调重写的handleMessage方法;如果是post(),会最后会回调 message.callback.run(),当前的run()方法。

  6. 在Activity中,我们并没有显示的调用Looper.prepare()和Looper.loop()方法,为啥Handler可以成功创建呢,这是因为在Activity的启动代码中,已经在当前UI线程调用了Looper.prepare()和Looper.loop()方法。

  7. 疑问:主线程死循环为什么不会卡死App?
    真正会卡死主线程的操作是在回调方法onCreate/onStart/onResume等操作时间过长,会导致掉帧,甚至发生ANR,looper.loop本身不会导致应用卡死。

来自https://www.jianshu.com/p/3466b47c7e77

相关文章

网友评论

      本文标题:Handler原理分析

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