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

Android Handler之消息如何回到Handler(三)

程序员文章站 2022-03-01 13:09:14
...

续上两篇
有关Handler你想要的都在这里了(一)
有关Handler你想要的都在这里了(二)
上篇我们讲到了当我们调用handler.sendMessage()最终的执行效果是在MessageQueue中插入了一条消息,然后代码无法跟踪了,给我们的源码阅读带来了困难,因为我们的思路断了,接下来怎么办呢?
还记得我们在有关Handler你想要的都在这里了(一)中的第四部分怎么从主线程发送消息到子线程?(虽然这种应用场景很少)中的示例代码吗?
示例代码中有这么一行代码

//启动Looper循环
 Looper.loop();

我们为什么要写这一行代码呢?
这个时候就要静下心来想一下了,我们的Message已经存到了MessageQueue中,那么是不是接下来就应该取消息并且处理消息了?带着这样的疑问,我查看了loop()方法的源码

  public static void loop() {
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }
            try {
                msg.target.dispatchMessage(msg);
            } 
        }
    }

同样的,为了降低阅读难度,我删掉了大部分的代码,只留下了这么几行核心代码,现在我们来看这几行代码的逻辑

这是一个死循环
这个循环的目的是从MessageQueue中取出消息
取消息的方法是MessageQueue.next()方法
取出消息后调用message.target对象的dispatchMessage()方法分发消息
循环跳出的条件是MessageQueue.next()方法返回了null

这也解释了为什么在子线程中要手动调用Looper.loop()方法
不过,看到这里我们应该自然会想到,message.target.是哪个对象?
该对象的dispatchMessage()方法都做了什么操作?
带着疑问,我们进入Message类中去寻找target

public final class Message implements Parcelable {
 /*package*/ int flags;

    /*package*/ long when;

    /*package*/ Bundle data;

    /*package*/ Handler target;

    /*package*/ Runnable callback;

    // sometimes we store linked lists of these things
    /*package*/ Message next;
}

看到了吧,Message类中有一个成员变量 target,而这个target是一个Handler,也就是说,在Looper从MessageQueue中取出Message之后,调用了Handler的dispatchMessage()方法。
这里我们不禁要问,这个target指向了哪个Handler?
带着这个疑问,我翻遍了Message类,也没有看到我想要的答案。此时我就想,既然Handler发送了消息就能接收到消息,那么会不会是在发送消息的途中发生了什么细节是我不知道的,那么我只好仔细看发送消息过程中的代码,终于让我发现了这个

//Handler的方法
 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

在这个方法的第一行代码就是,将message的target属性赋值为发送message的handler自身。如果读者忘记了这个方法的调用时机,请仔细参阅本系列博客一、二。
也就是说,Looper取出消息后,调用了发送消息的Handler的dispatchMessage()方法,并且将message本身作为参数传了回去。到此时,代码的执行逻辑又回到了Handler中。
接着看handler的dispatchMessage()方法

 /**
    *handler的方法
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

看到这里面一个我们非常熟悉到方法了没有?—handleMessage()方法,对,这个方法就是我们经常要重写的handleMessage()方法,也是我们处理消息时候的逻辑。
到这里,Handler机制工作的主要流程就完成了。
接下来,我们就应该慢慢回答有关Handler的问题了。