日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

【Android 异步操作】Handler 机制 ( MessageQueue 空闲任务 IdleHandler 机制 )

發布時間:2025/6/17 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Android 异步操作】Handler 机制 ( MessageQueue 空闲任务 IdleHandler 机制 ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 一、MessageQueue 空閑任務 IdleHandler 機制
  • 二、MessageQueue 中空閑任務 IdleHandler 相關源碼





一、MessageQueue 空閑任務 IdleHandler 機制



在 消息隊列 MessageQueue 的 next 獲取下一條消息的方法中 ,

在循環獲取消息的最后有如下代碼 :

public final class MessageQueue {@UnsupportedAppUsageMessage next() {// ...// 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)) {// 如果取出的 消息為空 , 就會執行 IdleHandlerpendingIdleHandlerCount = 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);// ...} }

開始判定 pendingIdleHandlerCount 大小 , 如果小于 000 則執行后續 與 IdleHandler 相關操作 ;

IdleHandler 是一個 接口 , 代碼如下 :

public final class MessageQueue {/*** Callback interface for discovering when a thread is going to block* waiting for more messages.*/public static interface IdleHandler {/*** Called when the message queue has run out of messages and will now* wait for more. Return true to keep your idle handler active, false* to have it removed. This may be called if there are still messages* pending in the queue, but they are all scheduled to be dispatched* after the current time.*/boolean queueIdle();} }

在上述如果取出的 mMessage 消息為空 mMessages == null , 則執行 IdleHandler ;


IdleHandler 使用時 , 調用 addIdleHandler 函數 , 該函數會將 IdleHandler 加入到 mIdleHandlers 集合中 ,

MessageQueue 消息隊列 addIdleHandler 函數如下 :

public final class MessageQueue {/*** Add a new {@link IdleHandler} to this message queue. This may be* removed automatically for you by returning false from* {@link IdleHandler#queueIdle IdleHandler.queueIdle()} when it is* invoked, or explicitly removing it with {@link #removeIdleHandler}.** <p>This method is safe to call from any thread.** @param handler The IdleHandler to be added.*/public void addIdleHandler(@NonNull IdleHandler handler) {if (handler == null) {throw new NullPointerException("Can't add a null IdleHandler");}synchronized (this) {mIdleHandlers.add(handler);}} }

在 MessageQueue 的 next 方法中繼續向下執行 , 開始遍歷 mIdleHandlers 集合 , 先將集合 mIdleHandlers 轉為 mPendingIdleHandlers 數組 , 然后遍歷該數組 ,

遍歷時 , 調用 IdleHandler 對象的 queueIdle 方法 ,

如果上面的 queueIdle 方法返回值是 false , 就會從 mIdleHandlers 集合中 移除該元素 ,

如果上面的 queueIdle 方法返回值是 true , 那么下一次再次執行到這里時 , 還會 繼續回調該函數 ;


上述操作對應的 MessageQueue 的 next 方法內的部分源碼 :

public final class MessageQueue {@UnsupportedAppUsageMessage next() {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 handlerboolean 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 = 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;} }

IdleHandler 的作用是 , 當消息隊列 MessageQueue 中沒有消息處理時 , 處于閑置狀態時 , 此時就會回調一次用戶注冊的 IdleHandler ,

如果該 IdleHandler 的 queueIdle 方法返回 false , 那么該 IdleHandler 只會 執行一次 ,

如果該 IdleHandler 的 queueIdle 方法返回 true , 則 每次空閑 , 都要執行一次該 IdleHandler ;





二、MessageQueue 中空閑任務 IdleHandler 相關源碼



public final class MessageQueue {@UnsupportedAppUsageMessage mMessages;@UnsupportedAppUsageprivate final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>();private IdleHandler[] mPendingIdleHandlers;@UnsupportedAppUsageMessage 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 iterationint 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.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 (DEBUG) Log.v(TAG, "Returning message: " + msg);msg.markInUse();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)) {// 如果取出的 消息為空 , 就會執行 IdleHandlerpendingIdleHandlerCount = 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 handlerboolean 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 = 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;}}/*** Callback interface for discovering when a thread is going to block* waiting for more messages.*/public static interface IdleHandler {/*** Called when the message queue has run out of messages and will now* wait for more. Return true to keep your idle handler active, false* to have it removed. This may be called if there are still messages* pending in the queue, but they are all scheduled to be dispatched* after the current time.*/boolean queueIdle();}}

總結

以上是生活随笔為你收集整理的【Android 异步操作】Handler 机制 ( MessageQueue 空闲任务 IdleHandler 机制 )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。