Android中消息处理机制研究 下篇

线程消息发送过程

1.通过调用sendMessageXXX方法将消息发送到一个消息队列中:

public boolean sendMessageAtTime(Message msg, long uptimeMillis)
    {
        boolean sent = false;
        MessageQueue queue = mQueue;
        if (queue != null) {
            msg.target = this;
            sent = queue.enqueueMessage(msg, uptimeMillis);//将消息发送到消息队列中
        }
        else {
            RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
        }
        return sent;
    }

2.调用enqueueMessage方法将消息插入到消息队列(队头或队中):

 boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
         throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
    throw new IllegalStateException(msg + " This message is already in use.");
        }

        synchronized (this) {
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
              msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }

            msg.markInUse();
            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);//如果线程正在睡眠,那么将其唤醒
            }
        }
        return true;
}

3.如果线程处于睡眠状态调用NativeMessageQueue的nativeWake方法,唤醒他:

static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) {
      NativeMessageQueue *nativeMessageQueue = reinterpret_cast<NativeMessageQueue*>(ptr);
      //通过ptr找到NativeMessageQueue,并调用它的wake方法唤醒目标线程,让它处理消息
      nativeMessageQueue->wake();
}

4.nativeWake方法中调用NativeMessageQueue的wake方法:

void NativeMessageQueue::wake() {
    mLooper->wake();//调用Looper(Native)的wake方法
}

5.wake方法中调用Looper(Native)的wake方法,向管道写入字符:

void Looper::wake() {
#if DEBUG_POLL_AND_WAKE
    LOGD("%p ~ wake", this);
#endif

#ifdef LOOPER_STATISTICS
    // FIXME: Possible race with awoken() but this code is for testing only and is rarely enabled.
    if (mPendingWakeCount++ == 0) {
        mPendingWakeTime = systemTime(SYSTEM_TIME_MONOTONIC);
   }
#endif

    ssize_t nWrite;
    do {
      nWrite = write(mWakeWritePipeFd, "W", 1);//向管道中写入字符,唤醒线程。
    } while (nWrite == -1 && errno == EINTR);

    if (nWrite != 1) {
        if (errno != EAGAIN) {
            LOGW("Could not write wake signal, errno=%d", errno);
        }
    }
}

线程消息处理过程
1.通过Looper类的loop方法获取消息:

public static void loop() {
        final Looper me = myLooper();//获取当前线程looper
        if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;//获取当前线程MessageQueue

      // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        for (;;) {//不断检查是否有新消息需要处理
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            // This must be in a local variable, in case a UI event sets the logger
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

            //msg.target指向一个Handler对象,调用Handler的dispatchMessage方法分发消息

            msg.target.dispatchMessage(msg); 
            if (logging != null) {
              logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) 
                        + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }

            msg.recycleUnchecked();
        }
    }

2.通过Handler类的dispatchMessage分发消息:

//分发Looper传来的消息
    public void dispatchMessage(Message msg) { 
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
           handleMessage(msg);
        }
    }

3.通过Handler的成员函数handleMessage处理消息:

//通过重写handleMessage方法处理消息
public void handleMessage(Message msg) {    }

相关阅读:Android中消息处理机制研究上篇

本文来自网易实践者社区,经作者曹兴授权发布。