{ Log.e("zjt", "delay ru" />

国产精品吹潮在线播放,日韩一区二区三区在线播放,啊级免费黄片视频,66av视频

android延遲執(zhí)行優(yōu)化 android延時執(zhí)行的幾種方式

更新時間:2023-08-25 09:08:02作者:未知

android延遲執(zhí)行優(yōu)化 android延時執(zhí)行的幾種方式

首先,需要明確一點,Handler 延時消息機制不是延時發(fā)送消息,而是延時去處理消息;舉個例子,如下:

handler.postDelayed(() ->{ Log.e("zjt", "delay runnable"); }, 3_000);

上面的 Handler 不是延時3秒后再發(fā)送消息,而是將消息插入消息隊列后等3秒后再去處理。

postDelayed 的方法如下:

public final boolean postDelayed(@NonNull Runnable r, long delayMillis) { return sendMessageDelayed(getPostMessage(r), delayMillis); }

其中的 getPostMessage 就是將 post 的 runnable 包裝成 Message,如下:

private static Message getPostMessage(Runnable r) { // 使用 Message.obtain() 避免重復(fù)創(chuàng)建實例對象,達到節(jié)約內(nèi)存的目的 Message m = Message.obtain(); m.callback = r; return m; }

sendMessageDelayed 方法如下:

public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } // 延時的時間是手機的開機時間(不包括手機休眠時間)+ 需要延時的時間 return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }

sendMessageAtTime 如下:

public boolean sendMessageAtTime(@NonNull 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); }

這里面的代碼很好理解,就不說了,看看 enqueueMessage:

private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg, long uptimeMillis) { msg.target = this; // 設(shè)置 msg 的 target 為Handler msg.workSourceUid = ThreadLocalWorkSource.getUid(); // 異步消息,這個需要配合同步屏障來使用,可以看我之前的文章,這里不贅述 if (mAsynchronous) { msg.setAsynchronous(true); } // 插入到 MessageQueue 中 return queue.enqueueMessage(msg, uptimeMillis); }

MessageQueue 的 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) { // 判斷發(fā)送消息的進程是否還活著 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(); // 標(biāo)記消息正在使用 msg.when = when; Message p = mMessages; // 獲取表頭消息 boolean needWake; // 如果隊列中沒有消息 或者 消息為即時消息 或者 表頭消息時間大于當(dāng)前消息的延時時間 if (p == null || when == 0 || when < p.when) { // New head, wake up the event queue if blocked. msg.next = p; mMessages = msg; // 表示要喚醒 Hander 對應(yīng)的線程,這個后面解釋 needWake = mBlocked; } else { 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; } // 喚醒Handler對應(yīng)的線程 if (needWake) { nativeWake(mPtr); } } return true; }

舉個例子,假設(shè)我們消息隊列是空的,然后我發(fā)送一個延時10s的延時消息,那么會直接把消息存入消息隊列。

從消息隊列中獲取消息是 通過 Looper.loop() 來調(diào)用 MessageQueue 的 next()方法,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(); } // 表示要休眠多長時間,功能類似于wait(time) // -1表示一直休眠, // 等于0時,不堵塞 // 當(dāng)有新的消息來時,如果handler對應(yīng)的線程是阻塞的,那么會喚醒 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) { // 計算延時消息的剩余時間 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; } ....... // 判斷是否有 idle 任務(wù),即主線程空閑時需要執(zhí)行的任務(wù),這個下面說 if (pendingIdleHandlerCount <= 0) { // 這里表示所有到時間的消息都執(zhí)行完了,剩下的如果有消息一定是延時且時間還沒到的消息; // 剛上面的 enqueueMessage 就是根據(jù)這個變量來判斷是否要喚醒handler對應(yīng)的線程 mBlocked = true; continue; } ...... } }

其實,從這里就可以看出來,Handler 的延時消息是如何實現(xiàn)的了。

比方說 發(fā)送一個延時10s的消息,那么在 next()方法是,會阻塞 (10s + 發(fā)送消息時的系統(tǒng)開機時間 – 執(zhí)行next()方法是系統(tǒng)的開機時間),到達阻塞時間時會喚醒?;蛘哌@時候有新的消息來了也會 根據(jù) mBlocked = true來喚醒。

IdleHandler是什么?

在 MessageQueue 類中有一個 static 的接口 IdleHanlder:

public static interface IdleHandler { boolean queueIdle(); }

當(dāng)MessageQueue中無可處理的Message時回調(diào); 作用:UI線程處理完所有事務(wù)后,回調(diào)一些額外的操作,且不會堵塞主進程;

接口中只有一個 queueIdle() 函數(shù),線程進入堵塞時執(zhí)行的額外操作可以寫這里, 返回值是true的話,執(zhí)行完此方法后還會保留這個IdleHandler,否則刪除。

本文標(biāo)簽: [db:關(guān)鍵詞]  

為您推薦

安卓應(yīng)用軟件排行榜(安卓手機應(yīng)用排行榜)

各位好,作為一名新人,在發(fā)了幾篇曬單之后,我深深地感受到應(yīng)該給同志們帶來一些干貨。今天瀏覽手機的時候,一個念頭突然閃現(xiàn)在我腦海。 把我珍藏多年的app給大家分享一下,豈不美哉? 所以推薦幾個好用但比較

2023-08-25 09:08

android延遲執(zhí)行優(yōu)化 android延時執(zhí)行的幾種方式

首先,需要明確一點,Handler 延時消息機制不是延時發(fā)送消息,而是延時去處理消息;舉個例子,如下:handler.postDelayed(() ->{ Log.e("zjt", "delay ru

2023-08-25 09:08

文字處理軟件有哪些(文字處理軟件有哪些?視頻講解)

想要成為一名合格的打工人,必須熟練掌握一些辦公技巧。但是大部分人對于辦公軟件的了解也大多在PPT、Word、Excel等軟件的操作上,卻忽略了其他可以提升辦公幸福感的小技巧。 其實人工智能時代,當(dāng)我

2023-08-25 09:08

dwg是什么文件格式 dwg格式文件如何轉(zhuǎn)為pdf

眾所周知,DWG是電腦中CAD軟件保存設(shè)計數(shù)據(jù)的專用文件格式,是一種圖紙文件。但是這種文件我們不能通過瀏覽器打開。所以我們需要將DWG轉(zhuǎn)化為PDF,該怎么轉(zhuǎn)換呢?大家學(xué)習(xí)下面這兩種方法,轉(zhuǎn)換就能輕松搞

2023-08-25 09:06

小說軟件有哪些(騰訊旗下的小說軟件有哪些)

網(wǎng)絡(luò)小說隨著07年國內(nèi)互聯(lián)網(wǎng)的普及,也隨之從萌芽狀態(tài)發(fā)展到了成長再到成熟,時至今日據(jù)數(shù)據(jù)統(tǒng)計,截止2018年上半年中國網(wǎng)絡(luò)小說用戶規(guī)模為4.06億人,伴隨著巨大的市場,那么各種的網(wǎng)絡(luò)小說APP也應(yīng)運而

2023-08-25 09:06

最新fcpx快捷鍵大全 fcpx基本操作

在Final Cut Pro中可以在命令-自定義,命令編輯器中進行查找或者更換 如果不知道命令的快捷鍵,可以點擊命令,后面則是它相對應(yīng)的快捷鍵 下面開始今天的教程,選中一個片段后按option鍵,

2023-08-25 09:06