Android應用程序消息處理機制(Looper、Handler)分析(8)
執行完這些IdleHandler之后,線程下次調用nativePollOnce函數時,就不設置超時時間了。
因為,很有可能在執行IdleHandler的時候,已經有新的消息加入到消息隊列中去了。
正因為如此,
要重置nextPollTimeoutMillis的值:
- [java] view plaincopy// While calling an idle handler, a new message could
- ve been delivered
- // so go back and look again for a pending message without waiting.
- nextPollTimeoutMillis = 0;
分析完MessageQueue的這個next函數之后,我們就要深入分析一下JNI方法nativePollOnce了,看看它是如何進入等待狀態的, 這個函數定義在frameworks/base/core/jni/android_os_MessageQueue.cpp文件中:
- [cpp] view plaincopystatic void
- android_os_MessageQueue_nativePollOnce(JNIEnv* env, jobject obj,
- jint ptr, jint timeoutMillis) {
- NativeMessageQueue* nativeMessageQueue =
- reinterpret_cast(ptr);
- nativeMessageQueue->pollOnce(timeoutMillis);
- }
這個函數首先是通過傳進入的參數ptr取回前面在Java層創建MessageQueue對象時在JNI層創建的NatvieMessageQueue對象,然后調用它的pollOnce函數:
- [cpp] view plaincopyvoid NativeMessageQueue::pollOnce(int timeoutMillis)
- mLooper->pollOnce(timeoutMillis);
- }
這里將操作轉發給mLooper對象的pollOnce函數處理,這里的mLooper對象是在C++層的對象,它也是在前面在JNI層創建的 NatvieMessageQueue對象時創建的,它的pollOnce函數定義在frameworks/base/libs/utils /Looper.cpp文件中:
- [cpp] view plaincopyint Looper::pollOnce(int timeoutMillis, int* outFd,
- t* outEvents, void** outData) {
- int result = 0;
- for (;;) {
- ......
- if (result != 0) {
- ......
- return result;
- }
- result = pollInner(timeoutMillis);
- }
- }
為了方便討論,我們把這個函數的無關部分都去掉,它主要就是調用pollInner函數來進一步操作,如果pollInner返回值不等于0,這個函數就可以返回了。
函數pollInner的定義如下:
- [cpp] view plaincopyint Looper::pollInner(int timeoutMillis) {
- ......
- int result = ALOOPER_POLL_WAKE;
- ......
- #ifdef LOOPER_USES_EPOLL
- struct epoll_event eventItems[EPOLL_MAX_EVENTS];
- int eventCount = epoll_wait(mEpollFd, eventItems, EPOLL_MAX_EVENTS,
- meoutMillis);
- bool acquiredLock = false;
- #else
- ......
- #endif
- if (eventCount < 0) {
- if (errno == EINTR) {
- goto Done;
- }
- LOGW("Poll failed with an unexpected error, errno=%d", errno);
- result = ALOOPER_POLL_ERROR;
- goto Done;
- }
- if (eventCount == 0) {
- ......
- result = ALOOPER_POLL_TIMEOUT;
- goto Done;
- }
- ......
- #ifdef LOOPER_USES_EPOLL
- 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();
- } else {
- LOGW("Ignoring unexpected epoll events 0x%x on wake read pipe.",
- ollEvents);
- }
- } else {
- ......
- }
- }
- if (acquiredLock) {
- mLock.unlock();
- }
- Done: ;
- #else
- ......
- #endif
- ......
- return result;
- }