欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Handler机制

程序员文章站 2022-07-14 15:09:48
...

Handler提供两种方式发送消息: post(runnable) 、 sendMessage(msg) , post 方式实现上也是通过 sendMessage 方法将消息发送出去的,区别在于 post 方法会先调用getPostMessage(runnable) 并将参数 runnable 赋值给创建好的 Message 对象的成员 callback 然后再调用 sendMessage(msg) 将消息发送出去;代码

public final boolean post(Runnable r) {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

注:sendMessage 内部是调用 sendMessageDelayed 方法

sendMessage(msg) 方法会先为传入的 msg 添加 target (即当前Handler),然后将这条消息通过 MessageQueue 的 enqueueMessage(msg) 方法添加到MessageQueue中( MessageQueue 用单链链表存储消息,对外提供 enqueueMessage(msg) 方法用于添加以及 next() 方法用于获取和移除消息);
Handler 只能在有 Looper 的线程中发送消息, Looper 是一个无限循环,用于从 MessageQueue 中取消息, Looper 中的 loop() 方法通过调用 MessageQueue 的 next 方法循环从 MessageQueue 中获取消息,获取到消息后调用 msg.target.dispatchMessage(msg) 将消息交给 Handler 处理, Handler 的处理逻辑:

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

首先判断 msg 的 callback 是否为空,这个 callback 就是 Handler 的 post(Runnable runnable) 方法传入的 runnable ,如果 msg.callback 不为空(即Handler通过post方法发送的消息)则调用 handleCallback(msg) 该方法中会回调 Runnable 的 run() 方法, msg.callback 为空的话则会判断 mCallback 是否为空, mCallback 是 Callback 的对象( Handler提供 Handler(Callback callback) 初始化方式,这种方式可以用来创建一个 Handler 的实例但并不需要派生 Handler 的子类。在日常开发中,创建 Handler 最常见的方式就是派生一个 Handler 的子类并重写其 handleMessage 方法来处理具体的消息,而 Callback 给我们提供了 另外一种使用 Handler 的方式,当我们不想派生子类时,就可以通过 Callback 来实现),当 mCallback 不为空时回调 mCallback 的 handleMessage(msg) 方法,否则调用 handleMessage(msg) 方法。

Handler.sendMessageDelayed() 如何实现:
sendMessageDelayed() 方法中调用 MessageQueue.enqueueMessage(msg, uptimeMillis),uptimeMillis 传入后会被赋值到 msg.when 中,在执行循环获取 Message 的时候会判断这个时间与当前时间,当前时间在指定时间前则将当前 Message 后移并跳过当前循环,知道当前时间在指定时间之后才将这个 Message 取出并执行。

相关标签: handler机制