Java?Handler同步屏障淺析講解
1.在View的加載和繪制流程這篇文章中:傳送門,有一個編舞者類,mChoreographer。
mTraversalBarrier = mHandler.getLooper().postSyncBarrier();
向MessageQueue中插入一條同步屏障消息,msg.target==null的消息,返回值mTraversalBarrier是一個int 的token值。
void scheduleTraversals() { if (!mTraversalScheduled) { mTraversalScheduled = true; //向消息隊列插入一個同步屏障的消息。msg.target==null的消息 mTraversalBarrier = mHandler.getLooper().postSyncBarrier(); mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); } }
mChoreographer.postCallback()方法會執(zhí)行mTraversalRunnable中的代碼。
mHandler.getLooper().removeSyncBarrier(mTraversalBarrier);
這個會根據(jù)上面產(chǎn)生的token值移出MessageQueue中的同步屏障消息。
final TraversalRunnable mTraversalRunnable = new TraversalRunnable(); final class TraversalRunnable implements Runnable { @Override public void run() { doTraversal(); } } void doTraversal() { if (mTraversalScheduled) { mTraversalScheduled = false; //移除同步屏障消息 mHandler.getLooper().removeSyncBarrier(mTraversalBarrier); //在這個方法中會調(diào)用 measure layout draw,view的繪制繪制流程的方法 performTraversals(); } }
還是看這行代碼mHandler.getLooper().postSyncBarrier(),系統(tǒng)是怎么處理的。
獲取了一個沒有設(shè)置handler的Message。
int enqueueSyncBarrier(long when) { // Enqueue a new sync barrier token. // We don't need to wake the queue because the purpose of a barrier is to stall it. synchronized (this) { final int token = mNextBarrierToken++; // 這個msg.target沒有被賦值 final Message msg = Message.obtain(); msg.markInUse(); msg.when = when; msg.arg1 = token; Message prev = null; Message p = mMessages; if (when != 0) { while (p != null && p.when <= when) { prev = p; p = p.next; } } if (prev != null) { // invariant: p == prev.next msg.next = p; prev.next = msg; } else { msg.next = p; mMessages = msg; } return token; } }
正常我們通過handler發(fā)送消息,handler是不允許為空的。
boolean enqueueMessage(Message msg, long when) { if (msg.target == null) { throw new IllegalArgumentException("Message must have a target."); } ........... }
那系統(tǒng)為啥要發(fā)送一個handler為空的消息呢?
先看mChoreographer發(fā)了同步屏障消息后,又做了什么?
又發(fā)送了一個異步消息:msg.setAsynchronous(true),這個消息的handler不為null。
private void postCallbackDelayedInternal(int callbackType, Object action, Object token, long delayMillis) { synchronized (mLock) { final long now = SystemClock.uptimeMillis(); final long dueTime = now + delayMillis; mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token); if (dueTime <= now) { scheduleFrameLocked(now); } else { Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action); msg.arg1 = callbackType; //將消息設(shè)置為異步消息 msg.setAsynchronous(true); mHandler.sendMessageAtTime(msg, dueTime); } } }
接下來看看MessageQueue是怎么去消息的,是如何對這個同步屏障消息怎么處理的。
Message next() { synchronized (this) { // Try to retrieve the next message. Return if found. final long now = SystemClock.uptimeMillis(); Message prevMsg = null; Message msg = mMessages; //如果msg.target==null說明我們已經(jīng)向消息隊里中插入了一條屏障消息。 //此時會進入到這個循環(huán)中,找到msg.isAsynchronous==true的異步消息。 //通常我們發(fā)送的都是同步消息isAsynchronous = false的,并且msg.target不能為null的。 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());//msg.isAsynchronous==true時結(jié)束循環(huán),說明找到了這個異步消息。 } 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; } } }
在取消的時候,先判斷進行msg.target為null的判斷,然后經(jīng)過while循環(huán),找到msg.isAsynchronous() == true的消息。也就是上面發(fā)送的異步消息。通常我們發(fā)送的消息都是同步消息,不會對對 msg.setAsynchronous(true);進行設(shè)置。
系統(tǒng)這樣做的目的就是為了優(yōu)先去處理這個異步消息。會把所有的同步消息放在后面,向一道屏障一樣,所以這樣的操作,被稱為同步屏障,是同步屏障消息的處理有更高的優(yōu)先級。
因為編舞者類mChoreographer 負責(zé)屏幕的渲染,需要及時的處理從底層過來的信號,以保障界面刷新的頻率。
那么mChoreographer是如何處理信號的,如何進行渲染的邏輯是怎么樣的,有機會再寫文章進行分享。
到此這篇關(guān)于Java Handler同步屏障淺析講解的文章就介紹到這了,更多相關(guān)Java Handler內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot中使用Activiti的方法教程(二)
工作流(Workflow),就是“業(yè)務(wù)過程的部分或整體在計算機應(yīng)用環(huán)境下的自動化”,下面這篇文章主要給大家介紹了關(guān)于Spring Boot中使用Activiti的相關(guān)資料,需要的朋友可以參考下2018-08-08Springmvc DispatcherServlet原理及用法解析
這篇文章主要介紹了Springmvc DispatcherServlet原理及用法解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09Java實現(xiàn)TCP/IP協(xié)議的收發(fā)數(shù)據(jù)(服務(wù)端)代碼實例
這篇文章主要介紹了Java實現(xiàn)TCP/IP協(xié)議的收發(fā)數(shù)據(jù)(服務(wù)端)代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-11-11