Handler Message
在Handler中,大致分為3種Message面睛,分別是同步消息辟宗,異步消息和同步屏障碗硬,他們?nèi)叨际荕essage,只是成員變量有些區(qū)別绵咱;
同步消息
也就是我一般使用的Message碘饼,再通過Handler進(jìn)行sendMessage到消息隊列,前提是構(gòu)造Handler時候傳的構(gòu)造參數(shù)async為false
Handler mHandler = new Handler()
//或者
Handler mHandler = new Handler(false)
通過以上mHandler發(fā)送的Message都是同步消息悲伶,且Message會與該mHandler綁定艾恼,即:
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//將Handler賦值給Message的target變量
msg.target = this;
//mAsynchronous為false,為同步消息
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
以上就是發(fā)送一個同步消息流程
異步消息
根據(jù)前面同步消息的發(fā)送流程可以知道拢切,只要通過構(gòu)造參async為true的Handler發(fā)送的Message都為異步消息蒂萎,即:
//構(gòu)造一個發(fā)送處理異步消息的Handler
Handler mHandler = new Handle(true)
所以通過這個mHandler發(fā)送的Message,在queueMessage時候淮椰,都會把Message的asynchronous設(shè)置為true五慈,即異步消息
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
//將Handler賦值給Message的target變量
msg.target = this;
//mAsynchronous為true,為異步消息
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
以上就是發(fā)送一個異步消息的流程
同步屏障
雖然沒有消息兩字主穗,但是同步屏障本質(zhì)也是Message對象泻拦,同步屏障個人覺得可以把它解釋為:屏障同步消息的消息,它和前面同步異步消息的最大區(qū)別就是忽媒,Message.target變量為null争拐,它的作用就是在消息隊列(MessageQueue)取出消息的時候,屏蔽掉同步消息晦雨,優(yōu)先獲取異步消息的作用
沒有同步屏障
假設(shè)下圖是沒有添加同步屏障的消息隊列
graph LR
B[同步消息A] --> C[同步消息B]
C[同步消息B] --> D[異步消息A]
那么在loop()循環(huán)從MessageQueue取出消息的順序是
- 同步消息A
- 同步消息B
- 異步消息A
- 睡眠等待消息插入...
有同步屏障
如果在消息隊列中插入同步屏障架曹,如下圖所示
graph LR
A[同步屏障]-->B[同步消息A]
B[同步消息A] --> C[同步消息B]
C[同步消息B] --> D[異步消息A]
那么在loop()循環(huán)從MessageQueue取出消息的順序是
- 異步消息A
- 睡眠等待消息插入...
此時消息隊列變?yōu)?/p>
graph LR
A[同步屏障]-->B[同步消息A]
B[同步消息A] --> C[同步消息B]
因為同步屏障在獲取消息的時候隘冲,屏蔽掉同步消息,只取出異步消息绑雄,那同步消息怎么辦展辞?只有當(dāng)同步屏障被屏蔽被移除的時候才能獲取到同步消息;
通過代碼在消息隊列添加同步屏障
//在MessageQueue類中万牺,添加同步屏障可以通過postSyncBarrier方法罗珍,該方法是被隱藏的,如果要調(diào)用的話只能通過反射機(jī)制進(jìn)行調(diào)用
public int postSyncBarrier() {
return postSyncBarrier(SystemClock.uptimeMillis());
}
private int postSyncBarrier(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++;
//創(chuàng)建一個Message對象脚粟,所以說同步屏障的本質(zhì)就是Message
//而且在這里看不到Message.target的賦值覆旱,所以可以說同步屏障和同步異步消息的區(qū)別就是target是否為空
final Message msg = Message.obtain();
msg.markInUse();
msg.when = when;
//記錄該同步屏障,后面可以通過token來移除該同步屏障
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;
}
//最后返回token扣唱,可以根據(jù)這個token移除同步屏障
return token;
}
}
//移除同步屏障
//token就是添加同步屏障時候返回的唯一標(biāo)示
public void removeSyncBarrier(int token) {
// Remove a sync barrier token from the queue.
// If the queue is no longer stalled by a barrier then wake it.
synchronized (this) {
Message prev = null;
Message p = mMessages;
//找到要移除的同步屏障位置
while (p != null && (p.target != null || p.arg1 != token)) {
prev = p;
p = p.next;
}
if (p == null) {
throw new IllegalStateException("The specified message queue synchronization "
+ " barrier token has not been posted or has already been removed.");
}
final boolean needWake;
if (prev != null) {
prev.next = p.next;
needWake = false;
} else {
mMessages = p.next;
needWake = mMessages == null || mMessages.target != null;
}
p.recycleUnchecked();
// If the loop is quitting then it is already awake.
// We can assume mPtr != 0 when mQuitting is false.
if (needWake && !mQuitting) {
nativeWake(mPtr);
}
}
}
通過自己代碼給消息隊列添加同步屏障
//獲取當(dāng)前線程Looper對象的消息隊列
MessageQueue queue=handler.getLooper().getQueue();
//通過反射調(diào)用
Method method=MessageQueue.class.getDeclaredMethod("postSyncBarrier");
token= (int) method.invoke(queue);
//移除同步屏障
//獲取當(dāng)前線程Looper對象的消息隊列
MessageQueue queue=handler.getLooper().getQueue();
Method method=MessageQueue.class.getDeclaredMethod("removeSyncBarrier",int.class);
method.invoke(queue,token);