1. Handler,Looper,MessageQueue,Message他們的作用與關(guān)系
1.1Handler
Handler使您可以發(fā)送和處理[Message](https://developer.android.com/reference/android/os/Message)
與線程的關(guān)聯(lián)的Runnable對(duì)象[MessageQueue](https://developer.android.com/reference/android/os/MessageQueue)
忆蚀。每個(gè)Handler實(shí)例都與一個(gè)線程和該線程的消息隊(duì)列關(guān)聯(lián)肢预。當(dāng)您創(chuàng)建新的處理程序時(shí)辞做,它會(huì)綁定到[Looper](https://developer.android.com/reference/android/os/Looper)
辱魁。它將消息和可運(yùn)行對(duì)象傳遞到該Looper的消息隊(duì)列寝杖,并在該Looper的線程上執(zhí)行它們拨拓。
Handler有兩個(gè)主要用途:(1)計(jì)劃消息和可運(yùn)行對(duì)象在將來(lái)的某個(gè)時(shí)刻執(zhí)行家制;(2)使要在與您自己的線程不同的線程上執(zhí)行的操作排隊(duì)暂雹。
以上是官方翻譯說(shuō)明策治,Handler在我們平常的使用主要是用于異步消息通知脓魏,在子線程中通知主線程做什么事,比ui刷新通惫,或者延時(shí)執(zhí)行某個(gè)操作茂翔。
1.2Message
定義一條消息,其中包含可以發(fā)送到的描述和任意數(shù)據(jù)對(duì)象[Handler](https://developer.android.com/reference/android/os/Handler)
履腋。該對(duì)象包含兩個(gè)額外的int字段和一個(gè)額外的對(duì)象字段珊燎,在很多情況下,這些字段使您不必進(jìn)行分配遵湖。
message是消息通知機(jī)制的載體悔政,Handler發(fā)送的信息都在放在Message中。
1.3MessageQueue
Low-level class holding the list of messages to be dispatched by a [Looper](https://developer.android.com/reference/android/os/Looper)
. Messages are not added directly to a MessageQueue, but rather through [Handler](https://developer.android.com/reference/android/os/Handler)
objects associated with the Looper.
You can retrieve the MessageQueue for the current thread with [Looper#myQueue()](https://developer.android.com/reference/android/os/Looper#myQueue())
.
消息隊(duì)列延旧,Handler發(fā)送的消息都在它這管理谋国,提供加入消息,和獲取消息的方法
1.4Looper
用于為線程運(yùn)行消息循環(huán)的類(lèi)迁沫。默認(rèn)情況下芦瘾,線程沒(méi)有與之關(guān)聯(lián)的消息循環(huán);要?jiǎng)?chuàng)建一個(gè)集畅,請(qǐng)[prepare()](https://developer.android.com/reference/android/os/Looper#prepare())
在要運(yùn)行循環(huán)的線程中調(diào)用 近弟,然后 [loop()](https://developer.android.com/reference/android/os/Looper#loop())
讓它處理消息,直到循環(huán)停止為止牡整。
與消息循環(huán)的大多數(shù)交互是通過(guò) [Handler](https://developer.android.com/reference/android/os/Handler)
類(lèi)進(jìn)行的藐吮。
Looper可以理解為一個(gè)循環(huán)執(zhí)行某個(gè)操作的類(lèi),這個(gè)類(lèi)是和線程綁定的。它的循環(huán)操作就是不斷的從MessageQueue中將可以發(fā)送的消息拿出來(lái)交給Handler處理
1.5他們之間的關(guān)系
- Handler發(fā)送消息 消息到哪了 谣辞?到messageQueue了 Handler(sendMessage)=====message====>MessageQueue
- Handler 處理消息 消息哪來(lái)的迫摔? Looper執(zhí)行它的循環(huán)拾取操作 MessageQueue======Message======>Handler(dispatch)
- Looper有一個(gè)MessageQueue消息隊(duì)列;
- MessageQueue有一組待處理的Message泥从;
- Message中有一個(gè)用于處理消息的Handler句占;
- Handler中有Looper和MessageQueue。
2.源碼解析
2.1 Handler源碼分析
Handler的創(chuàng)建躯嫉,構(gòu)造函數(shù)纱烘。這里講解兩個(gè)最重要的構(gòu)造函數(shù),其他的構(gòu)造方法都是調(diào)用這兩個(gè),發(fā)送消息和處理消息的方法
/**
* 使用當(dāng)前線程的Looper進(jìn)行Handler的創(chuàng)建
* Use the {@link Looper} for the current thread with the specified callback interface
* and set whether the handler should be asynchronous.
* <p>
* Handlers are synchronous by default unless this constructor is used to make
* one that is strictly asynchronous.
* <p>
* Asynchronous messages represent interrupts or events that do not require global ordering
* with respect to synchronous messages. Asynchronous messages are not subject to
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
*
* @param callback The callback interface in which to handle messages, or null.
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
* @hide
*/
public Handler(@Nullable Callback callback, boolean async) {
//匿名類(lèi)祈餐、內(nèi)部類(lèi)或本地類(lèi)都必須申明為static擂啥,否則會(huì)警告可能出現(xiàn)內(nèi)存泄露
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//獲取當(dāng)前線程的looper對(duì)象,myLooper方法會(huì)在講解Looper時(shí)進(jìn)行說(shuō)明
mLooper = Looper.myLooper();
if (mLooper == null) {//當(dāng)我們?cè)谧泳€程中創(chuàng)建Handler,并使用該構(gòu)造方法帆阳,就會(huì)報(bào)該錯(cuò)誤哺壶,
// 平時(shí)在主線程中創(chuàng)建Handler時(shí),已經(jīng)在創(chuàng)建Activity時(shí)生成了mainLooper,所以不需要?jiǎng)?chuàng)建
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
//相關(guān)屬性賦值蜒谤,獲取消息隊(duì)列
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
/**
* 使用自己傳入的Looper對(duì)象創(chuàng)建Handler
* Use the provided {@link Looper} instead of the default one and take a callback
* interface in which to handle messages. Also set whether the handler
* should be asynchronous.
* <p>
* Handlers are synchronous by default unless this constructor is used to make
* one that is strictly asynchronous.
* <p>
* Asynchronous messages represent interrupts or events that do not require global ordering
* with respect to synchronous messages. Asynchronous messages are not subject to
* the synchronization barriers introduced by conditions such as display vsync.
*
* @param looper The looper, must not be null.
* @param callback The callback interface in which to handle messages, or null.
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
* @hide
*/
@UnsupportedAppUsage
public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
//相關(guān)屬性賦值
mLooper = looper;
//獲取消息隊(duì)列
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
結(jié)論:所以從構(gòu)造方法我們就可以知道
- Handler中包含一個(gè)Looper山宾,LooperQueue
- 消息發(fā)送分為同步,與異步鳍徽,異步情況用的少
- looper分為自己傳入资锰,和Handler默認(rèn)獲取兩種。
Handler的創(chuàng)建既然已經(jīng)搞清楚了阶祭,就在看看它的消息發(fā)送功能,發(fā)送功能只分析比較重要的幾個(gè)方法
sendMessageAtTime發(fā)送消息在某個(gè)時(shí)間點(diǎn)
/**
* 發(fā)送消息 在某個(gè)時(shí)間
* Enqueue a message into the message queue after all pending messages
* before the absolute time (in milliseconds) <var>uptimeMillis</var>.
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
* Time spent in deep sleep will add an additional delay to execution.
* You will receive it in {@link #handleMessage}, in the thread attached
* to this handler.
*
* @param uptimeMillis The absolute time at which the message should be
* delivered, using the
* {@link android.os.SystemClock#uptimeMillis} time-base.
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the message will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;//獲取消息隊(duì)列
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);//加入消息到隊(duì)列
}
getPostMessage绷杜,將Runable轉(zhuǎn)換成Message,相當(dāng)于可以發(fā)送一個(gè)Runable接口濒募,又相當(dāng)于將一段Runable中運(yùn)行的代碼到消息隊(duì)列中接剩,又相當(dāng)于這段代碼運(yùn)行的線程是在Looper所在的線程中。
/**
* 將Runable轉(zhuǎn)換成Message的方法
*
* @param r 傳入一個(gè)Runable接口
* @return 返回一個(gè)Message對(duì)象
*/
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
sendMessageAtFrontOfQueue發(fā)送消息到隊(duì)列頭部
/**
* 發(fā)送一個(gè)消息到隊(duì)列最前面 uptimeMillis傳0 即可
* Enqueue a message at the front of the message queue, to be processed on
* the next iteration of the message loop. You will receive it in
* {@link #handleMessage}, in the thread attached to this handler.
* <b>This method is only for use in very special circumstances -- it
* can easily starve the message queue, cause ordering problems, or have
* other unexpected side-effects.</b>
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean sendMessageAtFrontOfQueue(@NonNull Message msg) {
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, 0);
}
enqueueMessage萨咳,加入消息到隊(duì)列
/**
* 加入消息到隊(duì)列
* @param queue 消息隊(duì)列
* @param msg 消息體
* @param uptimeMillis 發(fā)送時(shí)間
* @return 是否加入成功
*/
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true); //設(shè)置消息是同步還是異步懊缺,這里可以看出,要么全是同步培他,要么全是異步
}
return queue.enqueueMessage(msg, uptimeMillis);//調(diào)用消息隊(duì)列的enqueueMessage方法加入消息
}
Message的創(chuàng)建
/**
* Returns a new {@link android.os.Message Message} from the global message pool. More efficient than
* creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this).
* If you don't want that facility, just call Message.obtain() instead.
*/
@NonNull
public final Message obtainMessage() {
return Message.obtain(this);
}
結(jié)論
- 各種sendMesssage方法最后都會(huì)調(diào)用到MessageQueue的enqueueMessage
- 可以將Runable封裝成Message鹃两,并發(fā)送到Looper線程處理,也有與Runable匹配的各種sendMessage方法舀凛。
-Message的創(chuàng)建最好用Handler提供的obtainMessage()方法俊扳,這樣創(chuàng)建的對(duì)象是從對(duì)象池中獲取,減少開(kāi)銷(xiāo)猛遍。
下圖是sendMessage的一個(gè)調(diào)用鏈,便于理解
Handler可以sendMessage還可以處理消息dispatchMessage接下來(lái)看看處理消息相關(guān)分析
/**
* Handle system messages here.
*/
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {//如果msg的callBack不為空則交給handleCallback方法處理
handleCallback(msg);
} else {
if (mCallback != null) {//如果Handler的mCallback不為空馋记,這交給mCallback處理
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);//都沒(méi)人管交給Handler 的Handler處理
}
}
handleCallback
private static void handleCallback(Message message) {
message.callback.run();
}
handler的handleMessage方法
/**
* Subclasses must implement this to receive messages. 常用就是通過(guò)重寫(xiě)該方法實(shí)現(xiàn)消息處理邏輯
*/
public void handleMessage(@NonNull Message msg) {
}
Callback的上面已經(jīng)寫(xiě)了就不說(shuō)了号坡。
2.2 Message源碼分析
Message是消息傳遞的載體,可以理解成一個(gè)數(shù)據(jù)mode一樣,下面來(lái)分析一下它的重要屬性與重要方法,
重要屬性梯醒,常用的傳輸數(shù)據(jù)宽堆,比如arg,data茸习,what畜隶,等我就不做說(shuō)明了
//每個(gè)Message持有發(fā)送Handler的引用,哪來(lái)干什么呢号胚?當(dāng)然是調(diào)用handler.dispatch來(lái)處理消息了
@UnsupportedAppUsage
/*package*/ Handler target;
//上節(jié)講了籽慢,用于將callBack變成Message
@UnsupportedAppUsage
/*package*/ Runnable callback;
//這里next就代表一個(gè)鏈表,每個(gè)對(duì)象的next則指向它的下一個(gè)猫胁,當(dāng)用于回收池時(shí)箱亿,next就指向下一個(gè)回收對(duì)象
// 當(dāng)用于MessageQueue,就指向下一個(gè)需要處理的message弃秆。
// sometimes we store linked lists of these things
@UnsupportedAppUsage
/*package*/ Message next;
/**
* @hide 資源池的對(duì)象鎖
*/
public static final Object sPoolSync = new Object();
//Message 池子
private static Message sPool;
//當(dāng)前池子有的message數(shù)量
private static int sPoolSize = 0;
//池子最大值
private static final int MAX_POOL_SIZE = 50;
/**
* 回收Message是否進(jìn)行安全檢查极景,默認(rèn)為真
*/
private static boolean gCheckRecycle = true;
重要方法
得到一個(gè)Message對(duì)象,其他幾種方法都是調(diào)用這個(gè)方法得到message對(duì)象驾茴,并對(duì)Handler,callback氢卡,obj等屬性賦值锈至,就不說(shuō)明。理解Mesage回收池是一個(gè)比較重要的地方译秦,其中next的妙用峡捡,牛逼。
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
* 返回一個(gè)Message對(duì)象筑悴,從回收池中
*/
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {//回收池不為空
Message m = sPool; //spool對(duì)象給m
sPool = m.next;//spool的next變?yōu)殒湵淼谝粋€(gè)位置
m.next = null;//m對(duì)象next置空
m.flags = 0; // clear in-use flag
sPoolSize--; //線程池-1
return m;//返回message對(duì)象
}
}
return new Message();
}
回收一個(gè)Message對(duì)象到回收池
/**
* 回收消息们拙,當(dāng)回收一個(gè)正在inUse的Message默認(rèn)拋異常,gCheckRecycle默認(rèn)為ture阁吝,5.0以前默認(rèn)為false砚婆,以后默認(rèn)為true,安全第一呀
* Return a Message instance to the global pool.
* <p>
* You MUST NOT touch the Message after calling this function because it has
* effectively been freed. It is an error to recycle a message that is currently
* enqueued or that is in the process of being delivered to a Handler.
* </p>
*
*/
public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
recycleUnchecked();
}
/**
* 不安全的回收Message方法突勇,可能會(huì)回收一個(gè)處于in-use的Message
* Recycles a Message that may be in-use.
* Used internally by the MessageQueue and Looper when disposing of queued Messages.
*/
@UnsupportedAppUsage
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.恢復(fù)相關(guān)屬性到默認(rèn)值
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = UID_NONE;
workSourceUid = UID_NONE;
when = 0;
target = null;
callback = null;
data = null;
//這里說(shuō)明一下装盯,在完成一次回收后,sPool就變成剛剛回收的Message對(duì)象甲馋,而next就指向上一次的回收對(duì)象
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {//回收池中數(shù)量小于Max才進(jìn)行回收操作
next = sPool;//將當(dāng)前線程池的Message對(duì)象賦值給next
sPool = this;//將需要回收的這個(gè)對(duì)象引用給回收池--至此回收完成埂奈,回收池?cái)?shù)量+1,
sPoolSize++;
}
}
}
2.3 MessageQueue源碼解析
在Handler 中我們分析到sendMesage 最后調(diào)用到MessageQueue的enqueueMessage方法定躏,那我們從這個(gè)方法開(kāi)始分析账磺。
/**
* 向messageQueue message
*
* @param msg 加入的消息
* @param when 消息發(fā)送的時(shí)間
* @return 是否加入成功
*/
boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {//說(shuō)明必須要有target對(duì)象才能處理消息
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {//message正在處理芹敌,重復(fù)發(fā)送某個(gè)Message對(duì)象可能會(huì)出現(xiàn)這個(gè)問(wèn)題
throw new IllegalStateException(msg + " This message is already in use.");
}
,
synchronized (this) {
if (mQuitting) {//正在退出垮抗,將該msg回收氏捞,加入消息失敗
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)記當(dāng)前msg正在使用中
msg.when = when;//賦值消息處理時(shí)間
Message p = mMessages;//這里的mMessage就是待處理的一個(gè)鏈表隊(duì)列,
boolean needWake;
//當(dāng)p為空 代表啥借宵?代表該msg是MessageQueue隊(duì)列收到的第一個(gè)消息幌衣,它還是空的,啥也沒(méi)有
//when==0 代表啥壤玫?從前面可知 當(dāng)uptimeMillis為0,即現(xiàn)在的when豁护,表示要把它放在隊(duì)列最前面,
//when<p.when 嘛意思? 意思很簡(jiǎn)單欲间,我這個(gè)msg的執(zhí)行時(shí)間比你p列表最前面的還要早楚里,應(yīng)該讓我最先執(zhí)行
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
//所以if成立的執(zhí)行結(jié)果就很明顯了,1.將msg對(duì)象放在鏈表的首位over~
msg.next = p;
mMessages = msg;
needWake = mBlocked;//是否需要喚醒
} else {//執(zhí)行這個(gè)Block啥意思猎贴?就是msg肯定不在鏈表前面了該給他找個(gè)合適的位置了,排序操作班缎,排序條件when,
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (; ; ) {//循環(huán)操作
prev = p;//鏈表交給prev
p = p.next;//鏈表的老二變老大
if (p == null || when < p.when) {//p==?啥意思她渴,就是老二沒(méi)有达址,循環(huán)結(jié)束 when<p.when啥意思?新的老二已經(jīng)誕生了循環(huán)結(jié)束趁耗,哈哈
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
//msg可能是老二沉唠,老三。苛败。满葛。總之他去了該去的地方罢屈,一路走好~~~至此加入message完成
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
MessageQueue既然有了加入消息的方法嘀韧,獲取當(dāng)前待處理的消息就必不可少了,接下來(lái)讓我們看看MessageQueue的next方法如何提取消息
不看不知道缠捌,一看嚇一跳锄贷,next方法比enqueueMessage方法復(fù)雜多了.難道不是
Message message=mMessages;
mMessages=mMessages.next;
這么簡(jiǎn)單嗎,哈哈
@UnsupportedAppUsage
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;//native消息計(jì)數(shù)
if (ptr == 0) {
return null; //沒(méi)有消息
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (; ; ) {//死循環(huán)
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) {//當(dāng)target為null曼月,查詢(xún)異步消息
// Stalled by a barrier. Find the next asynchronous message in the queue.找到異步消息肃叶,退出循環(huán)
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());//遍歷msg獲取到符合條件的異步消息
}
if (msg != null) {
if (now < msg.when) {//還沒(méi)到消息發(fā)送時(shí)間,計(jì)算下一次執(zhí)行的時(shí)間
// 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 {//到時(shí)間了十嘿,找到了msg并返回
// 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) {//正在退出因惭,返回null
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)) {
pendingIdleHandlerCount = 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 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 = 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;
}
}
2.4Looper源碼解析
Looper通過(guò)調(diào)用MessageQueue 的next方法獲取到可以處理的message,并調(diào)用message.target.dispatch方法分發(fā)消息,完成消息處理最后的流程绩衷。接下來(lái)看看Looper的重要屬性蹦魔,與方法激率。
重要屬性
// sThreadLocal.get() will return null unless you've called prepare().
//ThreadLocal簡(jiǎn)稱(chēng)TLS線程本地存儲(chǔ)區(qū)域,用于線程存儲(chǔ)信息勿决,通過(guò)get乒躺,set方法,這里被用來(lái)存儲(chǔ)looper對(duì)象
@UnsupportedAppUsage
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
/**
* 主線程looperd對(duì)象
*/
@UnsupportedAppUsage
private static Looper sMainLooper; // guarded by Looper.class
private static Observer sObserver;
/**
* 消息隊(duì)列低缩,用于獲取笑嘻嘻
*/
@UnsupportedAppUsage
final MessageQueue mQueue;
/**
* looper所在的線程
*/
final Thread mThread;
重要方法
Looper的創(chuàng)建
/**
* Looper初始化
* @param quitAllowed
*/
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {//一個(gè)線程只有一個(gè)Looper
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));//創(chuàng)建Looper并存儲(chǔ)到TLS
}
Looper構(gòu)造函數(shù)
private Looper(boolean quitAllowed) {//創(chuàng)建Pooper
mQueue = new MessageQueue(quitAllowed);//創(chuàng)建MessageQueue Looper是否允許退出
mThread = Thread.currentThread();//當(dāng)前線程
}
獲取存儲(chǔ)的looper對(duì)象
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
* 從TLS中獲取Looper對(duì)象
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
Loop方法循環(huán)拾取MessageQueue的Message,這里只取了關(guān)鍵代碼部分嘉冒,其他關(guān)于日志log的進(jìn)行了刪減
for (; ; ) {//又見(jiàn)死循環(huán)
Message msg = queue.next(); // might block 從Messagequeue中獲取message
if (msg == null) {//沒(méi)有可以處理的消息,返回
// No message indicates that the message queue is quitting.
return;
}
msg.target.dispatchMessage(msg);//分發(fā)消息
msg.recycleUnchecked();//消息分發(fā)完成咆繁,進(jìn)行回收處理
}
}
Looper的queit方法
public void quit() {
mQueue.quit(false);//安全退出
}
public void quitSafely() {
mQueue.quit(true);不安全退出
}
MessageQueue的退出方法
//
void quit(boolean safe) {
//當(dāng)mQuitAllowed為false表示不能退出
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
if (mQuitting) {//如果正在退出返回
return;
}
mQuitting = true;
if (safe) {
removeAllFutureMessagesLocked();//移除所有未處理的消息
} else {
removeAllMessagesLocked();//移除所有消息讳推,包括處理中的
}
// We can assume mPtr != 0 because mQuitting was previously false.
nativeWake(mPtr);
}
}
總結(jié):Handler(sendMessage)message=========>MessageQueue======>Loop(取出消息)=====》Handler (dispatchMessage)就分析完畢
到這里Java層的Handler的消息機(jī)制差不多就清晰了。下面貼一張關(guān)系圖便于理解玩般。