new Handler().obtainMessage().sendToTarget()过程分析

来源:互联网 发布:反ip域名查询 编辑:程序博客网 时间:2024/06/07 11:40

new Handler().obtainMessage().sendToTarget()这句话用着真爽,一行代码就能搞定异步消息了!所以在代码中使用的算是非常频繁的了,那这又是一个什么样的过程呢? 这个过程中又有什么玄机呢? 这篇文章,我们来一步步的分析一下这三句话。


1、new Handler()的分析

new Handler()会辗转来到public Handler(Callback callback, boolean async)这个构造方法。在这个构造方法中会获取当前Looper

mLooper = Looper.myLooper();

而此时的Looper是默认的那个Looper,即在ActivityThreadmain方法中prepare的Looper

在ActivityThread.main中:

Looper.prepareMainLooper();...Looper.loop();

此时Handler和Looper有了关联。


2、obtainMessage()的分析

在Handler.obtainMessage()中会调用Message.obtain(this)。
Message.obtain()的源码:

public static Message obtain(Handler h) {        Message m = obtain();        m.target = h;        return m;  }

obtain从消息池中构造一个message,并将messagetarget置为传进来的handler


此时handlermessage有了关联。


3、sendToTarget()的分析

public void sendToTarget() {        target.sendMessage(this);}
直接调用target.sendMessage,而target正是当前的Handler。
继续跟踪target.sendMessage(this) target中发送消息会辗转来到private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)
在这个方法中有去调用queue.enqueueMessage.

继续跟踪queue.enqueueMessage,这个方法有点长,主要是将当前Message压入消息队列中:

...msg.when = when;Message p = mMessages;boolean needWake;if (p == null || when == 0 || when < p.when) {    // New head, wake up the event queue if blocked.    msg.next = p;    mMessages = msg;    needWake = mBlocked;} else {    // Inserted within the middle of the queue.  Usually we don't have to wake    // up the event queue unless there is a barrier at the head of the queue    // and the message is the earliest asynchronous message in the queue.    needWake = mBlocked && p.target == null && msg.isAsynchronous();    Message prev;    for (;;) {         prev = p;         p = p.next;         if (p == null || when < p.when) {                break;          }         if (needWake && p.isAsynchronous()) {               needWake = false;          }     }     msg.next = p; // invariant: p == prev.next     prev.next = msg; }// We can assume mPtr != 0 because mQuitting is false.if (needWake) {     nativeWake(mPtr);}...




这里面的MessageQueue就是在Handler保存的那个MessageQueue,也就是说此时,这个Message已经保存到Handler中的那个消息队列中了。而,我们Handler中的MessageQueue哪来的呢? 来看看这行代码:

public Handler(Callback callback, boolean async) {...mLooper = Looper.myLooper();...mQueue = mLooper.mQueue;...}

Handler中的MessageQueue正式从Looper中获取的,这个Looper当然就是在ActivityThread中prepare的那个。


顺一下此时的关系:Handler中保存了ActivityThread中的Looper,并从该Looper中获取了MessageQueue;调用obtainMessage,实质上是创建了一个Message对象,并将Message对象的target设置为现在的Handler;调用Message.sendToTarget()实际是调用了Message.target.sendMessage(),即Handler.sendMessage,而Handler.sendMessage会来到enqueueMessage方法,在这个方法中调用MessageQueue.enqueueMessage将消息压缩刚开始我们获取的那个MessageQueue。


此时,再来看看Looper.loop()是怎么将消息回调到handleMessage中的:

for (;;) {        Message msg = queue.next(); // might block        ...        msg.target.dispatchMessage(msg);        ...        msg.recycle(); }

继续看看Handler.dispatchMessage():

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

转来转去,终于把Message回调到了handleMessage!!!
从源码中,我们也能看出, sendToTarget()方法并不是真正的将Message发送出去,而是将Message压入了MessageQueue中,真正去回调handleMessage还是在Looper.loop()中完成的。



4 0
原创粉丝点击