Android(安卓)5 消息机制源码分析
消息模型
基本要素:
消息队列、消息发送、消息读取、消息分发、消息循环线程。
操作系统原理中的生产者线程和消费者线程有着类似的过程:
Android中的消息机制跟这个很类似,关键的几个名词如下:
- Handler
- Message
- Message Queue
- Looper
总览
这里是从网上找的一张图,在此感谢原作者。这里使用的是Android 5.1源码。
从这张图上我们可以大致看出Android中消息的执行过程。
Handler是依附于当前线程的,它在创建的时候,会使用当前线程的Looper来构造内部的消息循环系统。在Handler的运行过程中,由Handler发送一个Message给Handler所在线程的MessageQueue消息队列,Looper负责对消息进行转发处理。一个线程对应的Handler可以有多个,但是MessageQueue和Looper则只有一个。
Message
Message实现了Parcelable接口,是一个可序列化的类。
构造方法是一个空方法,注释中可以看到,建议使用obtian()去获取一个Message实例而不是通过new:
// sometimes we store linked lists of these things/*package*/ Message next;private static Message sPool;private static int sPoolSize = 0;private static final int MAX_POOL_SIZE = 50;/** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).*/public Message() {}/*** Return a new Message instance from the global pool. Allows us to* avoid allocating new objects in many cases.*/public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; m.flags = 0; // clear in-use flag sPoolSize--; return m; } } return new Message();}
这里的实现代码比较简单,第一次的时候sPool值为null,也就是会执行new操作,创建一个Message对象,之后会把这个对象进行复用,通过Message的结构可以看到,维持了一个类似链表的复用关系。sPool代表接下来要被重用的Message对象,sPoolSize表示被重用的对象数目;MAX_POOL_SIZE是pool的最大容量,默认为50个。
public void recycle() { if (isInUse()) { if (gCheckRecycle) { throw new IllegalStateException("This message cannot be recycled because it " + "is still in use."); } return; } recycleUnchecked();}/*** Recycles a Message that may be in-use.* Used internally by the MessageQueue and Looper when disposing of queued Messages.*/void recycleUnchecked() { // Mark the message as in use while it remains in the recycled object pool. // Clear out all other details. flags = FLAG_IN_USE; what = 0; arg1 = 0; arg2 = 0; obj = null; replyTo = null; sendingUid = -1; when = 0; target = null; callback = null; data = null; synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } } }
回收操作会导致每次被使用完毕的Message进入复用链。
MessageQueue
消息队列,这里就是一个单链表。学过数据结构大家都知道,对于链表的基本操作主要就是访问,插入和删除。这里主要是从消息队列中获取消息,以及往队列中插入一个消息。
private final boolean mQuitAllowed; @SuppressWarnings("unused") private long mPtr; // used by native code Message mMessages;//消息队列 private final ArrayList mIdleHandlers = new ArrayList(); private IdleHandler[] mPendingIdleHandlers; private boolean mQuitting; // Indicates whether next() is blocked waiting in pollOnce() with a non-zero timeout. private boolean mBlocked; // The next barrier token. // Barriers are indicated by messages with a null target whose arg1 field carries the token. private int mNextBarrierToken; private native static long nativeInit(); private native static void nativeDestroy(long ptr); private native static void nativePollOnce(long ptr, int timeoutMillis); private native static void nativeWake(long ptr); private native static boolean nativeIsIdling(long ptr);
mMessages指向消息队列。这列声明了几个Native方法,意味着Java层的实现依赖于C层。
首先看一下进队的操作:
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("MessageQueue", 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 //插入到队列中间通常不用唤醒事件队列,除非在队头部有一个同步分隔栏,并且这个消息是队列中最早进来的异步消息 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;}
首先判断了消息的target(其实就是发送消息的Handler)是否存在,又检查了当前这个消息是否正在使用。校验过了,会设置msg.markInUse();表明当前消息在使用中。接着就是插入单链表的操作了,判断链表当前是否为空,为空则插入的消息成为队首元素,采用头插法进行插入,不过需要注意同步分隔栏。最后,如果needWake为true,调用native方法nativeWake()唤醒。
看看这个函数做了啥:
【frameworks/base/core/jni/android_os_MessageQueue.cpp】
static JNINativeMethod gMessageQueueMethods[] = { /* name, signature, funcPtr */ { "nativeInit", "()J", (void*)android_os_MessageQueue_nativeInit }, { "nativeDestroy", "(J)V", (void*)android_os_MessageQueue_nativeDestroy }, { "nativePollOnce", "(JI)V", (void*)android_os_MessageQueue_nativePollOnce }, { "nativeWake", "(J)V", (void*)android_os_MessageQueue_nativeWake }, { "nativeIsIdling", "(J)Z", (void*)android_os_MessageQueue_nativeIsIdling }};
可以看到jni注册到了函数android_os_MessageQueue_nativeWake :
static void android_os_MessageQueue_nativeWake(JNIEnv* env, jclass clazz, jlong ptr) { NativeMessageQueue* nativeMessageQueue = reinterpret_cast(ptr); return nativeMessageQueue->wake();}void NativeMessageQueue::wake() { mLooper->wake();}
这里一看,又转到了Looper中去了。
【system/core/libutils/Looper.cpp】
void Looper::wake() {#if DEBUG_POLL_AND_WAKE ALOGD("%p ~ wake", this);#endif ssize_t nWrite; do { nWrite = write(mWakeWritePipeFd, "W", 1); } while (nWrite == -1 && errno == EINTR); if (nWrite != 1) { if (errno != EAGAIN) { ALOGW("Could not write wake signal, errno=%d", errno); } }}
这里向mWakeWritePipeFd管道里中写了个”W”。
接下来看看出队操作:
Message next() { // Return here if the message loop has already quit and been disposed. // This can happen if the application tries to restart a looper after quit // which is not supported. final long ptr = mPtr; if (ptr == 0) { return null; } int pendingIdleHandlerCount = -1; // -1 only during first iteration int nextPollTimeoutMillis = 0; for (;;) { if (nextPollTimeoutMillis != 0) { Binder.flushPendingCommands(); } nativePollOnce(ptr, nextPollTimeoutMillis); synchronized (this) { // Try to retrieve the next message. Return if found. final long now = SystemClock.uptimeMillis(); Message prevMsg = null; Message msg = mMessages;// 取消息队列里当前第一个消息 if (msg != null && msg.target == null) { // Stalled by a barrier. Find the next asynchronous message in the queue. // 如果从队列里拿到的msg是个“同步分割栏”,那么就寻找其后第一个“异步消息” do { prevMsg = msg; msg = msg.next; } while (msg != null && !msg.isAsynchronous()); } if (msg != null) { if (now < msg.when) { // Next message is not ready. Set a timeout to wake up when it is ready. nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE); } else { // Got a message. mBlocked = false; if (prevMsg != null) { prevMsg.next = msg.next; } else { mMessages = msg.next;// 重置消息队列的头部 } msg.next = null; if (false) Log.v("MessageQueue", "Returning message: " + msg); return msg; } } else { // No more messages. nextPollTimeoutMillis = -1; } // Process the quit message now that all pending messages have been handled. if (mQuitting) { dispose(); return null; } // If first time idle, then get the number of idlers to run. // Idle handles only run if the queue is empty or if the first message // in the queue (possibly a barrier) is due to be handled in the future. if (pendingIdleHandlerCount < 0 && (mMessages == null || now < mMessages.when)) { pendingIdleHandlerCount = mIdleHandlers.size(); } if (pendingIdleHandlerCount <= 0) { // No idle handlers to run. Loop and wait some more. mBlocked = true; continue; } if (mPendingIdleHandlers == null) { mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)]; } mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers); } // Run the idle handlers. // We only ever reach this code block during the first iteration. for (int i = 0; i < pendingIdleHandlerCount; i++) { final IdleHandler idler = mPendingIdleHandlers[i]; mPendingIdleHandlers[i] = null; // release the reference to the handler boolean keep = false; try { keep = idler.queueIdle(); } catch (Throwable t) { Log.wtf("MessageQueue", "IdleHandler threw exception", t); } if (!keep) { synchronized (this) { mIdleHandlers.remove(idler); } } } // Reset the idle handler count to 0 so we do not run them again. pendingIdleHandlerCount = 0; // While calling an idle handler, a new message could have been delivered // so go back and look again for a pending message without waiting. nextPollTimeoutMillis = 0; }}
这个方法有点儿长,主要就是从消息队列中取出一个消息,并从队列中移除。从for(;;)可以看出,这个是一个无线循环。nativePollOnce(ptr, nextPollTimeoutMillis);可能会阻塞。
if (msg != null && msg.target == null) { // Stalled by a barrier. Find the next asynchronous message in the queue. do { prevMsg = msg; msg = msg.next; } while (msg != null && !msg.isAsynchronous());}
这里从注释上,我们可以看到,当前队列如果被Barrier卡住,也就是队列中插了一个同步分隔栏,那么就去找队列中的下一个异步消息。方法最后有个IdleHandler的循环,当消息队列中没有消息需要马上处理时,会判断用户是否设置了Idle Handler,如果有的话,则会尝试处理mIdleHandlers中所记录的所有Idle Handler,此时会逐个调用这些Idle Handler的queueIdle()方法。
Looper
【frameworks/base/core/java/android/os/Looper.java】
public final class Looper { private static final String TAG = "Looper"; // sThreadLocal.get() will return null unless you've called prepare(). static final ThreadLocal sThreadLocal = new ThreadLocal(); private static Looper sMainLooper; // guarded by Looper.class final MessageQueue mQueue; final Thread mThread; private Printer mLogging; ...}
可以看到,Looper中维护了一个ThreadLocal变量,用于线程隔离存储。
public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
这两个方法是平时用的最多的,当我们在非UI线程中使用Handler时,一般都需要先创建一个Looper,然后才能发送消息。那么创建的操作就是这里的prepare方法。从代码的实现来看,当实例化Looper时,会把当前线程对应的Looper存储到ThreadLocal中,从而保证每个线程的Looper是唯一的,与其他线程之间隔离的。
此外还有如下的方法:
public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } } /** Returns the application's main looper, which lives in the main thread of the application. */ public static Looper getMainLooper() { synchronized (Looper.class) { return sMainLooper; } }
prepareMainLooper是给主线程使用的,我们可以在ActivityThread的main方法中看到它。而getMainLooper为在应用中获取主线程的Looper提供了便捷。
接下来看看Looper的主要方法loop():
/** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the loop. */public static void loop() { final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = me.mQueue; // 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.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(); }}
方法开始处获取Looper对象实例,并做了校验,下面这个异常相信大家都遇到过:”No Looper; Looper.prepare() wasn’t called on this thread.”
在获取到消息队列的实例之后,开始了无限循环。
关键的是下面这两句:
Message msg = queue.next();msg.target.dispatchMessage(msg);
第一个就是前面说过的MessageQueue的next()方法,阻塞式获取Message对象。
第二句,前面说过,这个target就是发送消息到MessageQueue的handler对象。把消息又转发到Handler的的handleMessage方法中去具体处理。这样看来,Looper其实就是一个中转的作用。
我们再进到MessageQueue的next()中看一下:
Message next() { // Return here if the message loop has already quit and been disposed. // This can happen if the application tries to restart a looper after quit // which is not supported. final long ptr = mPtr; if (ptr == 0) { return null; } int pendingIdleHandlerCount = -1; // -1 only during first iteration int nextPollTimeoutMillis = 0; for (;;) { if (nextPollTimeoutMillis != 0) { Binder.flushPendingCommands(); } nativePollOnce(ptr, nextPollTimeoutMillis); ...}
刚才看过这个方法,不过这个地方有个nativePollOnce没有分析。nativePollOnce()起到了阻塞作用,保证消息循环不会在无消息处理时一直在那里空跑。看看这个Native方法是怎么实现的?
从前面的注册器上看:
实现在jni函数:android_os_MessageQueue_nativePollOnce
static void android_os_MessageQueue_nativePollOnce(JNIEnv* env, jclass clazz, jlong ptr, jint timeoutMillis) { NativeMessageQueue* nativeMessageQueue = reinterpret_cast(ptr); nativeMessageQueue->pollOnce(env, timeoutMillis);}void NativeMessageQueue::pollOnce(JNIEnv* env, int timeoutMillis) { mInCallback = true; mLooper->pollOnce(timeoutMillis); mInCallback = false; if (mExceptionObj) { env->Throw(mExceptionObj); env->DeleteLocalRef(mExceptionObj); mExceptionObj = NULL; }}
这个地方又出现了一个Looper。这个是Looper在C++层的实现,那这个有什么不一样的地方么?
【system/core/include/utils/Looper.h】
【system/core/libutils/Looper.cpp】
看下构造函数:
Looper::Looper(bool allowNonCallbacks) : mAllowNonCallbacks(allowNonCallbacks), mSendingMessage(false), mResponseIndex(0), mNextMessageUptime(LLONG_MAX) { int wakeFds[2]; // 创建管道 int result = pipe(wakeFds); LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe. errno=%d", errno); // 管道的“读取端” mWakeReadPipeFd = wakeFds[0]; // 管道的“写入端” mWakeWritePipeFd = wakeFds[1]; //读 result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK); LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking. errno=%d", errno); //写 result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK); LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking. errno=%d", errno); mIdling = false; // 创建epoll实例,并注册唤醒管道 mEpollFd = epoll_create(EPOLL_SIZE_HINT); LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance. errno=%d", errno); struct epoll_event eventItem; memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union eventItem.events = EPOLLIN; eventItem.data.fd = mWakeReadPipeFd; // 监听管道读取端 result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem); LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance. errno=%d", errno);}
这段代码来看,是在Looper中创建了一个管道,然后通过epoll监听管道的读取端,当向消息队列发送消息时,最终是向管道的写入端写入数据。前面写入”W”只是一个通知有消息来了。
接着前面看下pollOnce函数:int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) { int result = 0; for (;;) { ... if (result != 0) { ... if (outFd != NULL) *outFd = 0; if (outEvents != NULL) *outEvents = 0; if (outData != NULL) *outData = NULL; return result; } result = pollInner(timeoutMillis); }}
调到了pollInner函数:
int Looper::pollInner(int timeoutMillis) { ... // Poll. int result = POLL_WAKE; mResponses.clear(); mResponseIndex = 0; // We are about to idle. mIdling = true; struct epoll_event eventItems[EPOLL_MAX_EVENTS]; int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis); .... for (int i = 0; i < eventCount; i++) { int fd = eventItems[i].data.fd; uint32_t epollEvents = eventItems[i].events; if (fd == mWakeReadPipeFd) {//这个是唤醒的读管道描述符 if (epollEvents & EPOLLIN) { awoken();//从管道中感知到EPOLLIN,调用awoken() } else { ALOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.", epollEvents); } } else {//其他情况的消息事件 ssize_t requestIndex = mRequests.indexOfKey(fd); if (requestIndex >= 0) { int events = 0; if (epollEvents & EPOLLIN) events |= EVENT_INPUT; if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT; if (epollEvents & EPOLLERR) events |= EVENT_ERROR; if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP; pushResponse(events, mRequests.valueAt(requestIndex)); } else { ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is " "no longer registered.", epollEvents, fd); } } }Done: ; //调用等待处理的消息回调 // Invoke pending message callbacks. mNextMessageUptime = LLONG_MAX; while (mMessageEnvelopes.size() != 0) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0); if (messageEnvelope.uptime <= now) { .... { // obtain handler sp handler = messageEnvelope.handler; Message message = messageEnvelope.message; mMessageEnvelopes.removeAt(0); mSendingMessage = true; mLock.unlock(); handler->handleMessage(message); } // release handler mLock.lock(); mSendingMessage = false; result = POLL_CALLBACK; } else { // The last message left at the head of the queue determines the next wakeup time. mNextMessageUptime = messageEnvelope.uptime; break; } } ....... //调用所有response记录的回调 for (size_t i = 0; i < mResponses.size(); i++) { Response& response = mResponses.editItemAt(i); if (response.request.ident == POLL_CALLBACK) { int fd = response.request.fd; int events = response.events; void* data = response.request.data;#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS ALOGD("%p ~ pollOnce - invoking fd event callback %p: fd=%d, events=0x%x, data=%p", this, response.request.callback.get(), fd, events, data);#endif int callbackResult = response.request.callback->handleEvent(fd, events, data); if (callbackResult == 0) { removeFd(fd); } response.request.callback.clear(); result = POLL_CALLBACK; } } return result;}
从上面的代码中,我们可以看到,当有消息事件发过来时,首先Looper.loop()会通过queue.next()从MessageQueue中取消息,此时可能会在next()方法中阻塞,也就是nativePollOnce(ptr, nextPollTimeoutMillis);方法做的事。这里会继续调到C++层,通过android_os_MessageQueue_nativePollOnce(xxx)将时间值传递给nativeMessageQueue->pollOnce(xxx);接着处理逻辑就转移到了C++层的Looper中处理。由mLooper->pollOnce(timeoutMillis);调到pollOnce函数,然后调用pollInner(timeoutMillis),在这个函数中对请求的消息和响应做了处理:
int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
这里将时间值设置给epoll_wait函数,也就是获取消息事件等待的超时时间了。
当eventCount大于0时,意味着有消息事件来了,我们比较关心的是fd == mWakeReadPipeFd的情况,我们看到这里调用了awoken()唤醒函数;
void Looper::awoken() {#if DEBUG_POLL_AND_WAKE ALOGD("%p ~ awoken", this);#endif char buffer[16]; ssize_t nRead; do { nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer)); } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));}
这里只是从管道的读取端进行读数据操作。
Handler
构造函数:
public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async;}public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = callback; mAsynchronous = async;}
这里又是经常看到的异常信息了。
下面这个也是一个常用的方法,实际上调用的也是Message的obtain方法。
public final Message obtainMessage(){ return Message.obtain(this);}
我们通常使用的发送消息方法:
public final boolean sendMessage(Message msg){ return sendMessageDelayed(msg, 0);}public final boolean sendEmptyMessage(int what){ return sendEmptyMessageDelayed(what, 0);}public final boolean post(Runnable r){ return sendMessageDelayed(getPostMessage(r), 0);}public final boolean postAtTime(Runnable r, long uptimeMillis){ return sendMessageAtTime(getPostMessage(r), uptimeMillis);}public final boolean postDelayed(Runnable r, long delayMillis){ return sendMessageDelayed(getPostMessage(r), delayMillis);}
最后都会调用到同一个方法:
public boolean sendMessageAtTime(Message msg, long uptimeMillis) { MessageQueue queue = mQueue; if (queue == null) { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); return false; } return enqueueMessage(queue, msg, uptimeMillis);}private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis);}
其实也就做了一件事情,就是在uptimeMillis时间计时完成前把消息插入消息队列中。
在Looper.java的loop()方法中,调用到msg.target.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); } }
最后会走到handler的handleMessage方法对消息进行处理。
更多相关文章
- Android(安卓)js和原生交互
- Android(安卓)View框架总结(一)
- Android图片圆角 用简单的方法实现
- Android(安卓)activity的生命周期
- Android(安卓)WebView获取cookie
- Android(安卓)JNI NDK Eclipse 设定(避免出现重复build的设定方
- (Android) Eclipse "launching delegate" 停在 27%的解决方法
- 浅谈Java中Collections.sort对List排序的两种方法
- Python list sort方法的具体使用