目錄:

1. 背景
在上一篇關(guān)于 Android Handler 使用方法 的文章中學(xué)會(huì)了 Handler 的使用方法,然而又是知其然不知其所以然的狀態(tài),這次較深入的學(xué)習(xí)一下 Handler 的源碼。
在分析源碼之前,先來了解一下Message、MessageQueue、Looper這幾個(gè)對(duì)象。
1.1 Message 消息
定義:是線程間通訊的數(shù)據(jù)單元,包含著描述信息及任意數(shù)據(jù)對(duì)象,發(fā)送到 Handler。
在實(shí)際使用中,我們?cè)诠ぷ骶€程中通過 Handler.sendMessage(Message),將攜帶數(shù)據(jù)的 Message 信息發(fā)送給 Handler,然后再由 Handler 處理,根據(jù)不同的信息,通知主線程作出相對(duì)應(yīng)的 UI 工作。
官方文檔說明:
/**
* 定義包含著描述信息及任意數(shù)據(jù)對(duì)象的可發(fā)送到 Handler 的信息。額外包含可以不被分配的兩個(gè) int 字段及一個(gè) Object 字段。
* 獲取 Message 對(duì)象最好的方法是調(diào)用 Message.obtain() 或 調(diào)用 Handler.obtainMessage() 方法來獲取,調(diào)用該方法將從可回收的對(duì)象池中獲取對(duì)象。
*/
public final class Message implements Parcelable {
/**
* 用戶定義的消息代碼,以便接收者能夠識(shí)別此消息。每個(gè) Handler 都有自己的消息代碼命名空間,因此不必?fù)?dān)心你的 Handler 與其他 Handler 起沖突。
*/
public int what;
/**
* 如果只需要存儲(chǔ)幾個(gè)整數(shù)值,以 arg1 和 arg2 為變量去使用 setData(Bundle) 是較低成本的替代選擇方法。
*/
public int arg1;
public int arg2;
/**
* 發(fā)送給接收者的任意對(duì)象,當(dāng)使用 Messager 跨進(jìn)程發(fā)送消息時(shí),如果包含著可序列化的框架類時(shí),Message必須是非空的。使用setData()來傳輸數(shù)據(jù)。
* 注意,Android 2.2發(fā)行版之前不支持此處的Parcelable對(duì)象。
*/
public Object obj;
···略···
1.2 MessageQueue 消息隊(duì)列
定義:用來存儲(chǔ) Message 的數(shù)據(jù)隊(duì)列。
官方文檔說明:
/**
* 包含著一系列由 Looper 分發(fā)的 Message 的一個(gè)低級(jí)類。
* Message 不是直接添加到 MessageQueue 中的,而是通過與 Looper 關(guān)聯(lián)的 Handler 對(duì)象來添加的。
* 你可以使用“l(fā)oop.myQueue()”方法來獲取當(dāng)前線程的 MessageQueue 對(duì)象。
*/
public final class MessageQueue {
private static final String TAG = "MessageQueue";
···略···
}
1.3 Looper 消息循環(huán)器
定義:用于為線程執(zhí)行消息循環(huán)的一個(gè)類。是 MessageQueue 與 Handler 之間的通訊媒介。
官方文檔說明:
/**
* 用于為線程執(zhí)行消息循環(huán)的一個(gè)類。
* 線程默認(rèn)情況下沒有與之關(guān)聯(lián)的消息循環(huán);要?jiǎng)?chuàng)建一個(gè),在將要運(yùn)行循環(huán)的線程中調(diào)用 Looper.prepare(),然后調(diào)用 Looper.loop() 讓它處理消息,直到循環(huán)停止。
* 與消息循環(huán)的大多數(shù)交互都是通過 Handler 類進(jìn)行的。
* 這是一個(gè)典型的 Looper 線程實(shí)現(xiàn)的例子,使用 Looper.prepare() 和 Looper.loop() 方法創(chuàng)建一個(gè) Handler 對(duì)象與 Looper 進(jìn)行通信。
* <pre>
* class LooperThread extends Thread {
* public Handler mHandler;
*
* public void run() {
* Looper.prepare();
*
* mHandler = new Handler() {
* public void handleMessage(Message msg) {
* // 在這里處理傳入的消息
* }
* };
*
* Looper.loop();
* }
* }</pre>
*/
public final class Looper {
/*
* API 實(shí)現(xiàn)注意事項(xiàng):
*
* 該類包含設(shè)置和管理基于 MessageQueue 的事件循環(huán)所需的代碼。
* 影響隊(duì)列狀態(tài)的api應(yīng)該在 MessageQueue 或 Handler 上定義,而不是在 Looper 本身上定義。
* 例如,在隊(duì)列上定義空閑處理程序和同步屏障,而在 Looper 上定義線程準(zhǔn)備、循環(huán)和退出。
*/
private static final String TAG = "Looper";
···略···
}
1.4 Message、MessageQueue、Looper之間的關(guān)系
一句話概括:
存儲(chǔ)在 MessageQueue 中的 Message 被 Looper 循環(huán)分發(fā)到指定的 Handler 中進(jìn)行處理。
2. Handler 通信機(jī)制原理
關(guān)于Handler的通信機(jī)制工作原理,請(qǐng)看 Carson_Ho大佬的 Android Handler:圖文解析 Handler通信機(jī)制 的工作原理 寫的超棒,圖文解析,一目了然。引用其中一Handler通信流程示意圖,如下:
Thread、Handler、Looper三者之間的數(shù)量對(duì)應(yīng)關(guān)系;
- 一個(gè) Thread 可以有多個(gè) Handler。
- 一個(gè) Handler 只能關(guān)聯(lián)一個(gè) Looper 對(duì)象。
- 反之,一個(gè) Looper 可以被多個(gè) Handler 所關(guān)聯(lián)。
3. 源碼分析
根據(jù)上一篇博客中介紹的Android Handler 使用方法, 我們針對(duì) Handler.sendMessage(msg) 方法展開分析,分為3步:
- 創(chuàng)建 Handler 對(duì)象
- 創(chuàng)建 Message 對(duì)象
- 分發(fā) Message
3.1 創(chuàng)建 Handler 對(duì)象
創(chuàng)建一個(gè) Handler 對(duì)象,也就是實(shí)例化一個(gè) Handler 對(duì)象,在實(shí)際的使用中,我也發(fā)現(xiàn)有存在三種情況,分別是:
- 在主線程上新建一個(gè) Handler 對(duì)象,提供應(yīng)用程序的 主Looper 對(duì)象與之綁定關(guān)聯(lián)。
- 創(chuàng)建一個(gè)繼承于 Handler類的靜態(tài)內(nèi)部類,防止內(nèi)存泄漏。
- 在子線程上創(chuàng)建 Handler 對(duì)象。
我將一一展開分析:
3.1.1 在主線程上新建一個(gè) Handler 對(duì)象,提供應(yīng)用程序的 主Looper 對(duì)象與之綁定關(guān)聯(lián)
如下,我們?cè)谥骶€程中新建 Handler 對(duì)象,
//在主線程中新建 Handler 對(duì)象,并提供應(yīng)用程序的 主Looper
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//消息處理
}
};
通過上述代碼,我們創(chuàng)建了一個(gè) Handler 對(duì)象,并關(guān)聯(lián)應(yīng)用程序的 主Looper 對(duì)象。
這個(gè)時(shí)候我們看一下 Handler類 的構(gòu)造函數(shù),如下所示:
/**
* Use the provided {@link Looper} instead of the default one.
* 使用提供的 Looper對(duì)象, 而不是使用默認(rèn)的Looper對(duì)象
* @param Looper 不能為 null
*/
public Handler(@NonNull Looper looper) {
this(looper, null, false);
}
可以發(fā)現(xiàn),我們提供給 Handler 的 Looper 是通過 Looper.getMainLooper() 獲取的。往下看:
/**
* 返回應(yīng)用程序的 主Looper, 它存在于應(yīng)用程序的主線程中。
*/
public static Looper getMainLooper() {
synchronized (Looper.class) {
//返回sMainLooper, 下一步看看sMainLooper是怎么創(chuàng)建 Looper 對(duì)象的。
return sMainLooper;
}
}
如上所訴,getMainLooper() 返回 全局變量 sMainLooper 對(duì)象,所以我們需要看 sMainLooper 是什么時(shí)候被賦值的,如下所示,在 prepareMainLooper() 方法中,sMainLooper 被 myLooper 賦值:
/**
* 將當(dāng)前線程初始化為 Looper,并將其標(biāo)記為應(yīng)用程序的 主Looper
* 應(yīng)用程序的 主Looper 是由 Android環(huán)境 創(chuàng)建的,所以永遠(yuǎn)不需要自己調(diào)用這個(gè)函數(shù)
*/
public static void prepareMainLooper() {
//調(diào)用 prepare() 方法,如果當(dāng)前線程沒有 Looper 對(duì)象,就為之新創(chuàng)建一個(gè) Looper 對(duì)象。
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
//返回當(dāng)前線程所關(guān)聯(lián)的 Looper 對(duì)象。
sMainLooper = myLooper();
}
}
上一步 prepareMainLooper 中:調(diào)用了 prepare(false) 來創(chuàng)建 Looper 對(duì)象,具體如下:
private static void prepare(boolean quitAllowed) {
//sThreadLocal.get() 返回 Looper || null,如果返回 Looper 對(duì)象,即代表已經(jīng)為該線程創(chuàng)建了 Looper 對(duì)象,
//從而拋出異常,提示:“每個(gè)線程只能創(chuàng)建一個(gè)Looper”
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//否則,調(diào)用 new Looper()方法新建一個(gè) Looper 對(duì)象,并放入 sThreadLocal 變量中。
sThreadLocal.set(new Looper(quitAllowed)); //quitAllowed = false
}
上一步 prepare() 中:調(diào)用了 new Looper() 方法來新創(chuàng)建 Looper 對(duì)象,具體如下:
private Looper(boolean quitAllowed) {
//新建一個(gè) MessageQueue
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
在 prepareMainLooper() 方法中,如果 sMainLooper 為 null,就賦值 sMainLooper = myLooper(); , myLooper() 方法如下:
/**
* 返回當(dāng)前線程所關(guān)聯(lián)的 Looper 對(duì)象,如果所調(diào)用的線程沒有關(guān)聯(lián)的 Looper 對(duì)象,就返回 null
*/
public static @Nullable Looper myLooper() {
//獲取的 Looper 對(duì)象,是在 prepare() 方法中通過 sThreadLocal.set(new Looper(quitAllowed)); 所創(chuàng)建的
return sThreadLocal.get();
}
上述代碼中,getMainLooper() 方法中的 sMainLooper 是通過 prepareMainLooper() 進(jìn)行賦值的,具體代碼分析如上所述,其流程圖如下所示:
3.1.2 創(chuàng)建一個(gè)繼承于 Handler類的靜態(tài)內(nèi)部類,防止內(nèi)存泄漏
上述創(chuàng)建 Handler 對(duì)象的方法是 new Handler(Looper.getMainLooper()) ,通過 Looper.getMainLooper() 方法獲取 Looper 對(duì)象,然后傳入到 Handler 的構(gòu)造函數(shù)中,構(gòu)成綁定關(guān)聯(lián)關(guān)系。
但在實(shí)際開發(fā)中,我們通常將 Handler 寫成靜態(tài)內(nèi)部類的形式,如下:
//創(chuàng)建 Handler 對(duì)象
mHandler = new MyHandler(this);
/**
* 將 Handler 寫成靜態(tài)內(nèi)部類,防止內(nèi)存泄露
*/
public static class MyHandler extends Handler {
WeakReference<HandlerAddThreadActivity> weakReference;
public MyHandler(HandlerAddThreadActivity activity) {
weakReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//處理收到的信息
}
}
思考: 疑問?根據(jù)上面的代碼,我們沒有傳遞 Looper 對(duì)象給 Handler 去綁定關(guān)聯(lián), 那 Handler 為何又能正常工作?
帶著疑惑上路:
首先看一下 Handler類 的默認(rèn)構(gòu)造函數(shù)
/**
* 默認(rèn)構(gòu)造函數(shù)將這個(gè)處理程序與當(dāng)前線程的{@link Looper}關(guān)聯(lián)起來。
* 如果此線程沒有l(wèi)ooper,則此處理程序?qū)o法接收消息,因此將引發(fā)異常。
*/
public Handler() {
this(null, false);
}
public Handler(@Nullable Callback callback, boolean async) {
···略···
//返回與當(dāng)前線程關(guān)聯(lián)的Looper對(duì)象。如果調(diào)用線程沒有關(guān)聯(lián)的 Looper 對(duì)象,則返回null
mLooper = Looper.myLooper();
//如果 mLooper 為null,則拋出異常。
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
//獲取該 Looper 的 MessageQueue
mQueue = mLooper.mQueue;
//callback = null && async = false
mCallback = callback;
mAsynchronous = async;
}
看著不明顯,mLooper 是通過 Looper.myLooper() 方法獲得的.
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
但這個(gè)時(shí)候我想起了 prepareMainLooper() 方法。
/**
* 將當(dāng)前線程初始化為 Looper,并將其標(biāo)記為應(yīng)用程序的 主Looper
* 應(yīng)用程序的 主Looper 是由 Android環(huán)境 創(chuàng)建的,所以永遠(yuǎn)不需要自己調(diào)用這個(gè)函數(shù)
*/
public static void prepareMainLooper() {
//調(diào)用 prepare() 方法,如果當(dāng)前線程沒有 Looper 對(duì)象,就為之新創(chuàng)建一個(gè) Looper 對(duì)象。
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
//返回當(dāng)前線程所關(guān)聯(lián)的 Looper 對(duì)象。
sMainLooper = myLooper();
}
}
疑問解除,無論我們有沒有手動(dòng)添加 Looper 給 Handler, Android環(huán)境都會(huì)為我們自動(dòng)創(chuàng)建一個(gè)主線程的主Looper對(duì)象。
總結(jié): 我們創(chuàng)建的 MyHandler 靜態(tài)內(nèi)部類,其實(shí)也是在主線程上創(chuàng)建的, Android環(huán)境會(huì)為我們自動(dòng)創(chuàng)建一個(gè)應(yīng)用程序的 主Looper 對(duì)象,主線程與 主Looper 綁定關(guān)聯(lián)。
3.1.3 在子線程上創(chuàng)建 Handler 對(duì)象
ok, 解除了剛剛的疑問,我又問自己,那在子線程創(chuàng)建 Handler 對(duì)象呢?
當(dāng)然,如果你在子線程中新創(chuàng)建一個(gè) Handler 對(duì)象,創(chuàng)建的方法為:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
//為當(dāng)前線程創(chuàng)建一個(gè) Looper
Looper.prepare();
//在子線程中創(chuàng)建 Handler 對(duì)象
mHandler = new Handler() {
public void handleMessage(Message msg) {
// 在這里處理傳入的消息
}
};
//開始消息循環(huán)
Looper.loop();
}
}
在子線程上,我們通過調(diào)用 prepare() 來為當(dāng)前線程創(chuàng)建一個(gè) Looper 對(duì)象
/** 將當(dāng)前線程初始化為 Looper 對(duì)象,在實(shí)際開始循環(huán)之前創(chuàng)建并引用該 Looper 對(duì)象。
* 請(qǐng)確保在調(diào)用此方法后調(diào)用 loop() 方法,并通過調(diào)用 quit() 結(jié)束它
*/
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
并且在 Handler 與 Looper 構(gòu)成綁定關(guān)聯(lián)關(guān)系后,通過調(diào)用 Looper.loop() 方法開始消息循環(huán)。
3.2 創(chuàng)建 Message消息對(duì)象
關(guān)于創(chuàng)建 Message 對(duì)象有兩種創(chuàng)建方法,分別是:
- Message myMessage = new Message();
- Message myMessage = Message.obtain()
/**
* 從全局池返回一個(gè)新的消息實(shí)例。允許我們?cè)谠S多情況下避免分配新對(duì)象。
*/
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
本文不過多展示。
3.3 發(fā)送消息
在工作線程中通過調(diào)用 mHandler.sendMessage(myMessage); 方法來發(fā)送消息,這一步是消息入消息隊(duì)列操作,即將 Message 入 MessageQueue。
/**
* 在當(dāng)前時(shí)間之前所有掛起的消息之后, 將消息推到消息隊(duì)列的末尾。它將該線程所關(guān)聯(lián)的 Handler 的 handleMessage 方法中被接收消息。
* @return 如果信息成功加入到消息隊(duì)列中,返回 true,反之,入隊(duì)列失敗則返回 false, 失敗的原因通常是因?yàn)樘幚硐㈥?duì)列的“l(fā)ooper”正在退出。
*/
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
/**
* 延時(shí) delayMillis 將消息入消息隊(duì)列,它將該線程所關(guān)聯(lián)的 Handler 的 handleMessage 方法中被接收消息。
* @return 如果信息成功加入到消息隊(duì)列中,返回 true,反之,入隊(duì)列失敗則返回 false, 失敗的原因通常是因?yàn)樘幚硐㈥?duì)列的 Looper 正在退出。
* 注意,true的結(jié)果并不意味著將處理該消息——如果 Looper 在消息的交付時(shí)間之前退出,則該消息將被刪除。
*/
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
//默認(rèn) delayMillis = 0
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
/**
* 在指定時(shí)間入隊(duì)列,深度睡眠的時(shí)間會(huì)增加額外的執(zhí)行延遲。它將該線程所關(guān)聯(lián)的 Handler 的 handleMessage 方法中被接收消息。
* @param uptimeMillis 發(fā)送消息的絕對(duì)時(shí)間,使用{SystemClock # uptimeMillis}獲取。
* @return 如果信息成功加入到消息隊(duì)列中,返回 true,反之,入隊(duì)列失敗則返回 false, 失敗的原因通常是因?yàn)樘幚硐㈥?duì)列的 Looper 正在退出。
* 注意,true的結(jié)果并不意味著將處理該消息——如果 Looper 在消息的交付時(shí)間之前退出,則該消息將被刪除。
*/
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
//獲取當(dāng)前 Looper 對(duì)象的消息隊(duì)列
MessageQueue queue = mQueue;
//如果當(dāng)前 Looper 對(duì)象沒有消息隊(duì)列,則拋出異常,返回 false, 代表消息入隊(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ì)列
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
根據(jù)消息的處理時(shí)間入消息隊(duì)列
boolean enqueueMessage(Message msg, long when) {
//獲得當(dāng)前的 Handler 對(duì)象,如果為 null, 則拋出異常
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
//如果消息已經(jīng)被使用,即已經(jīng)入隊(duì)列,則拋出異常
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
//如果 Looper 已經(jīng)退出,拋出異常,入隊(duì)列失敗,返回false
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();
msg.when = when;
Message p = mMessages;
boolean needWake;
//如果隊(duì)列里沒有消息,或者新消息的處理時(shí)間排在最前,即作為消息隊(duì)列新的隊(duì)頭插入消息隊(duì)列
if (p == null || when == 0 || when < p.when) {
//新的隊(duì)列頭部,如果隊(duì)列是 blocked 的狀態(tài)則需要喚醒該事件隊(duì)列。
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
//插入處理時(shí)間插入到隊(duì)列的中間。通常我們不需要喚醒事件隊(duì)列,除非是隊(duì)列頭部的屏障,并且消息是隊(duì)列中最早的異步消息
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;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
3.4 消息循環(huán),派發(fā)消息
消息入 MessageQueue 隊(duì)列后,由 Looper 循環(huán)消息隊(duì)列,然后派發(fā)消息,如下所示:
/**
* 在線程中運(yùn)行消息隊(duì)列,并確保調(diào)用 quit() 方法來結(jié)束消息循環(huán)
*/
public static void loop() {
//獲取當(dāng)前線程關(guān)聯(lián)的 Looper 對(duì)象,如果該線程沒有關(guān)聯(lián)的 Looper 對(duì)象,則拋出異常
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//獲取該 Looper 對(duì)象的消息隊(duì)列
final MessageQueue queue = me.mQueue;
//循環(huán)消息隊(duì)列
for (;;) {
//取出消息隊(duì)列中的消息對(duì)象,如果消息隊(duì)列為空,則 block 該線程。
Message msg = queue.next(); // might block
if (msg == null) {
//沒有消息則表明消息隊(duì)列正在退出,解除消息循環(huán)
return;
}
try {
//消息對(duì)應(yīng)的 Handler 分發(fā)消息
msg.target.dispatchMessage(msg);
}
//回收正在使用的消息
msg.recycleUnchecked();
}
}
/**
* 處理系統(tǒng)消息
*/
public void dispatchMessage(@NonNull Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//如果 Message.callback 為空,執(zhí)行 handleMessage(msg),即回調(diào)復(fù)寫 handleMessage(msg) 方法。
handleMessage(msg);
}
}
/**
* 回收可能正在使用的消息,由 MessageQueue 和 Looper 在處理排隊(duì)消息時(shí)在內(nèi)部使用。
*/
void recycleUnchecked() {
//將消息標(biāo)記為正在使用,同時(shí)將其保留在回收的對(duì)象池中。并清楚其余所有細(xì)節(jié)
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;
···
}
Looper 消息循環(huán),發(fā)送消息給指定的 Handler中,觸發(fā)我們覆寫的 handleMessage(Message) 方法。
至此,關(guān)于 Android Handler.sendMessage() 的源碼就分析完了。
其實(shí)分享文章的最大目的正是等待著有人指出我的錯(cuò)誤,如果你發(fā)現(xiàn)哪里有錯(cuò)誤,請(qǐng)毫無保留的指出即可,虛心請(qǐng)教。
另外,如果你覺得文章不錯(cuò),對(duì)你有所幫助,請(qǐng)給我點(diǎn)個(gè)贊,就當(dāng)鼓勵(lì),謝謝~Peace~!