设为首页 加入收藏

TOP

深入理解 Handler 消息机制(三)
2019-09-06 00:27:03 】 浏览:141
Tags:深入 理解 Handler 消息 机制
Millis = 0,不会阻塞,立即返回。 // 如果 nextPollTimeoutMillis > 0,最长阻塞nextPollTimeoutMillis毫秒(超时),如果期间有程序唤醒会立即返回。 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.target == null表示此消息为消息屏障(通过postSyncBarrier方法发送来的) // 如果发现了一个消息屏障,会循环找出第一个异步消息(如果有异步消息的话), // 所有同步消息都将忽略(平常发送的一般都是同步消息) 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. // 得到 Message mBlocked = false; if (prevMsg != null) { prevMsg.next = msg.next; } else { mMessages = msg.next; } msg.next = null; if (DEBUG) Log.v(TAG, "Returning message: " + msg); msg.markInUse(); // 标记 FLAG_IN_USE 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. // Idle handle 仅当队列为空或者队列中的第一个消息将要执行时才会运行 if (pendingIdleHandlerCount < 0 && (mMessages == null || now < mMessages.when)) { pendingIdleHandlerCount = mIdleHandlers.size(); } if (pendingIdleHandlerCount <= 0) { // No idle handlers to run. Loop and wait some more. // 没有 idle handler 需要运行,继续循环 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(TAG, "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 置零保证不再运行 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; } }

next() 方法是一个死循环,但是当没有消息的时候会阻塞,避免过度消耗 CPU。nextPollTimeoutMillis 大于 0 时表示等待下一条消息需要阻塞的时间。等于 -1 时表示没有消息了,一直阻塞到被唤醒。

这里的阻塞主要靠 native 函数 nativePollOnce() 来完成。其具体原理我并不了解,想深入学习的同学可以参考 Gityuan 的相关文 Android消息机制2-Handler(Native层)

MessageQueue 提供了消息入队和出队的方法,但它自己并不是自动取消息。那么,谁来把消息取出来并执行呢?这就要靠 Looper 了。

Looper

创建 Handler 之前必须先创建 Looper,而主线程已经为我们自动创建了 Looper,无需再手动创建,见 ActivityThread.javamain() 方法:

public static void main(String[] args) {
...
 Looper.prepareMainLooper(); // 创建主线程 Looper
.
首页 上一页 1 2 3 4 5 下一页 尾页 3/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇基于wanAndroid-项目实战 下一篇Android几种多渠道打包

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目