版權(quán)聲明: 本文來自 書生依舊 的簡書普气,轉(zhuǎn)載請注明出處煌张。
原文鏈接: http://www.reibang.com/p/1a5a3db45cfa
一. What换可、Handler 是什么
Handler 與 Message跨算、MessageQueue右钾、Looper 一起構(gòu)成了 Android 的消息機制轻要,Android 系統(tǒng)通過大量的消息來與用戶進行交互抹凳,View 的繪制、點擊事件伦腐、Activity 的生命周期回調(diào)等都作為消息由主線程的 Handler 來處理赢底。
Handler 在消息機制中的作用是:發(fā)送和處理消息。
Handler 還有另一個重要的作用柏蘑,跨線程通信幸冻。最常見的就是子線程請求網(wǎng)絡(luò),然后使用 Handler 將請求到的數(shù)據(jù) post 到主線程刷新 UI咳焚,大名鼎鼎的 Retrofit 也是這么做的洽损。
二. How、如何使用 Handler
-
創(chuàng)建 Handler
private Handler handler = new Handler() { // 重寫 handleMessage 來根據(jù)不同 what 來處理 Message // 這個方法在 Handler 創(chuàng)建的線程執(zhí)行 @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 0: MLog.i(msg.obj); break; case 1: break; default: } } };
-
創(chuàng)建并發(fā)送 Message
// 獲取一個 Message Message message = Message.obtain(); message.what = 0; message.obj = new Object(); // 使用 Handler 發(fā)送 Message // 消息發(fā)送完成后 Handler 的 handleMessage(Message msg) 會處理消息 handler.sendMessage(message); // 延遲 1s 發(fā)送 Message handler.sendMessageDelayed(message, 1000); // 發(fā)送一個空的 Message handler.sendEmptyMessage(msg.what); // 延遲發(fā)送一個空的 Message handler.sendEmptyMessageDelayed(0, 1000); // 還可以這樣 // 創(chuàng)建 Message 并綁定 Handler Message message = handler.obtainMessage(); message.what = 0; message.obj = new Object(); // 發(fā)送 Message message.sendToTarget();
-
使用 Handler 子線程請求數(shù)據(jù)革半,主線程刷新 UI
// 1. 在主線程創(chuàng)建 Handler(略) // 2. 子線程請求數(shù)據(jù)碑定,主線程刷新 UI new Thread(new Runnable() { @Override public void run() { // 獲取網(wǎng)絡(luò)數(shù)據(jù) final List<Object> datas = getNetData(); // 方法一:將數(shù)據(jù)作為 Message 的 obj 發(fā)送出去,在 handleMessage 中刷新 UI Message msg = Message.obtain(); msg.what = 1; msg.obj = data; handler.sendMessage(msg); // 方法二:直接在 post 中刷新 UI handler.post(new Runnable() { @Override public void run() { // 使用 datas 刷新 UI // 這個方法也會在 Handler 創(chuàng)建的線程執(zhí)行 } }); } }).start();
三. Handler 的內(nèi)存泄漏
不得不說又官,上面使用 Handler 的方法會有內(nèi)存泄漏的風險
-
Handler 內(nèi)存泄漏的兩個原因
-
Java 中非靜態(tài)內(nèi)部類和匿名內(nèi)部類會持有外部類的引用
// 這是一個外部類 Handler 不會持有外部類引用 // 顯然 handleMessage 沒地方寫了 Handler handler = new Handler(); // 重寫 handleMessage 后將得到一個內(nèi)部類 Handler延刘,以內(nèi) handleMessage 是在外部類中實現(xiàn)的 // 它持有外部類引用,可能會引起內(nèi)存泄漏 Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 0: MLog.i(msg.obj); break; case 1: break; default: } } }; // 這里 Handler 是一個匿名類六敬,但不是內(nèi)部類 // Runnable 是一個匿名內(nèi)部類碘赖,持有外部類引用,可能會引起內(nèi)存泄漏 new Handler().post(new Runnable() { @Override public void run() { // ... } });
?
Handler 的生命周期比外部類長外构。
-
-
分析
- 非靜態(tài)的內(nèi)部 Handler 子類普泡、匿名 Handler 子類會持有外部類的引用(Activity),而 Handler 可能會因為要等待處理耗時操作導致存活時間超過 Activity审编,或者消息隊列中存在未被 Looper 處理的 Message 撼班,而 Message 會持有 Handler 的引用。于是垒酬,在 Activity 退出時砰嘁,其引用還是被 Handler 持有眯亦,導致 Activity 無法被及時回收,造成內(nèi)存泄露般码。
- 非靜態(tài)的內(nèi)部 Runnable 子類妻率、匿名 Runnable 子類 post 到任意 Handler 上時,Runnable 其實是 Massage中的 Callback板祝,持有 Message 引用宫静,如果這個 Massage 在消息隊列還沒有被處理,那么就會造成 Runnable 一直持有外部類的引用而造成內(nèi)存泄露券时。
-
解決方案:
- 通過靜態(tài)內(nèi)部類或者外部類來聲明 Handler 和 Runnable孤里。
- 通過弱引用來拿到外部類的變量。
- 在 Activity/Fragment 銷毀的時候請空 MessageQueue 中的消息橘洞。
-
代碼
// Handler 弱引用封裝 public class SafetyHandler<T> extends Handler { /** * 外部引用, 例如 Activity, Fragment, Dialog, View 等 */ private WeakReference<T> mTargetRef; public SafetyHandler() { } public SafetyHandler(T target) { this.mTargetRef = new WeakReference<>(target); } public T getTarget() { if (isTargetAlive()) { return mTargetRef.get(); } else { removeCallbacksAndMessages(null); return null; } } public void setTarget(T target) { this.mTargetRef = new WeakReference<>(target); } private boolean isTargetAlive() { return mTargetRef != null && mTargetRef.get() != null; } } // 在 Fragment 中使用方法 // 想重寫 handleMessage 的話捌袜,要創(chuàng)建靜態(tài)內(nèi)部類或者外部類,否則有內(nèi)存泄漏風險 private static class MyHandler extends SafetyHandler<MyFragment> { MyHandler(MyFragment fragment) { super(fragment); } @Override public void handleMessage(Message msg) { super.handleMessage(msg); if(getTarget() != null) { MyFragment fragment = getTarget(); switch (msg.what) { // 操作 fragment } } } } // 聲明 Handler MyHandler handler = new MyHandler(this); // 使用 Handler handler.sendMessage() ... // onDestroy @Override public void onDestroy() { super.onDestroy(); handler.removeCallbacksAndMessages(null); }
?
四. Why炸枣、Handler 消息機制的原理
這部分從 ActivityThread 的 main 方法出發(fā)虏等,打通整個消息機制的流程,結(jié)合源碼體驗效果更佳适肠。
概述
介紹消息機制的原理前霍衫,我們先來看一下 Handler 與 Message、MessageQueue侯养、Looper 這個四個類的作用
- Handler:前面已經(jīng)說過敦跌,Handler 負責發(fā)送和處理 Message。
- Message:消息逛揩,負責傳遞標示(what) 和數(shù)據(jù)(obj) 柠傍;每個 Message 都會通過 target 這個成員變量來綁定一個 Handler,由這個 Handler 來發(fā)送和處理 Message辩稽。
- MessageQueue:消息隊列惧笛,負責存放有 Handler 發(fā)送過來的消息;每個 Handler 中都有一個 final MessageQueue mQueue搂誉,Handler 發(fā)送消息就是把消息加入這個 MessageQueue 徐紧。
- Looper:負責不斷的從 MessageQueue 中取出消息然后交給 Handler(Message#target ) 處理;每個 Looper 中都有一個唯一的消息隊列(final MessageQueue mQueue)炭懊,每個 Handler 中都有一個 final Looper mLooper,Handler 中的 MessageQueue 就是來自 Looper拂檩。
注意:每個線程只能有一個 Looper 和 一個 MessageQueue侮腹,可以有多個 Handler,每個 Handler 可以發(fā)送和處理多個 Message稻励。
另外父阻,提到消息機制就不得不說一下 Android 中的主線程(UI 線程)
Android 中的主線程通過 Looper.loop() 進入一個無線循環(huán)中愈涩,不斷的從一個 MessageQueue 取出消息,處理消息加矛,我們每觸發(fā)一個事件履婉,就會向這個 MessageQueue 中添加一個消息,Looper 取出這個消息斟览,Handler 處理這個消息毁腿,正是 Looper.loop() 在驅(qū)動著 Android 應用運行下去 ,這也是為什么 Looper.loop 為什么不會阻塞住主線程的原因(當然前提是在 ActivityThread 的 main 函數(shù) 中調(diào)用)苛茂。
正式進入源碼分析
本源碼分析基于 API 25已烤,以下源碼中刪除了一些無關(guān)的代碼
1、在主線程的入口妓羊,ActivityThread 的 main 方法
public static void main(String[] args) {
// 準備主線程的 Looer
Looper.prepareMainLooper();
// 創(chuàng)建 ActivityThread
ActivityThread thread = new ActivityThread();
thread.attach(false);
// 獲取主線程的 Handler
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
// 對消息隊列進行無線輪詢胯究,處理消息
Looper.loop();
// 一旦跳出循環(huán),拋出異常(Android 不允許跳出主線程的 Looper.loop())
throw new RuntimeException("Main thread loop unexpectedly exited");
}
-> Looper.prepareMainLooper()
public static void prepareMainLooper() {
// 準備一個 Looper
prepare(false);
synchronized (Looper.class) {
// main Looper 只能初始化一次躁绸,再次初始化會拋出異常
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
// 獲取 main Looper
sMainLooper = myLooper();
}
}
-> prepare(false)
// 準備一個 Looper裕循,quitAllowed 是否允許 Looper 中的 MessageQueue 退出
// 默認 prepare() 允許退出,主線程這里不允許退出
private static void prepare(boolean quitAllowed) {
// 先看下 sThreadLocal 是什么
// static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
// ThreadLocal:線程本地存儲區(qū)净刮,每個線程都有本地存儲區(qū)域费韭,這個區(qū)域是每個線程私有的,不同的線程不能之間不能彼此訪問
// 如果 sThreadLocal 中有數(shù)據(jù)庭瑰,拋出異常星持,換句話說 prepare() 這個函數(shù)每個線程只能執(zhí)行一次
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 創(chuàng)建 Looper 保存到該線程的 ThreadLocal 中
sThreadLocal.set(new Looper(quitAllowed));
}
-> new Looper(quitAllowed)
private Looper(boolean quitAllowed) {
// 在 Looper 創(chuàng)建的時候創(chuàng)建一個消息隊列
// quitAllowed:消息隊列是否可以退出,主線的消息隊列肯定不允許退出弹灭,所以上面是 prepare(false)
// quitAllowed 為 false 執(zhí)行 MessageQueue#quit 退出消息隊列時會出現(xiàn)異常
mQueue = new MessageQueue(quitAllowed);
// 獲取 Looper 存在于哪個線程
mThread = Thread.currentThread();
}
-> sMainLooper = myLooper()
public static @Nullable Looper myLooper() {
// 從 sThreadLocal 中獲取當前線程的 Looper
// 如果當前線程沒有掉用 Looper.prepare 返回 null
return sThreadLocal.get();
}
-> sMainThreadHandler = thread.getHandler();
final Handler getHandler() {
// 返回 mH
return mH;
}
// mH 在成員變量的位置 new H()
final H mH = new H();
// H 繼承了 Handler 封裝了一系列關(guān)于 Acitivty督暂、Service 以及其他 Android 相關(guān)的操作
private class H extends Handler
總結(jié):在主線程的 main 方法中乔遮,會創(chuàng)建主線程的 Looper辨赐、MessageQueue,然后進入 Looper.loop() 循環(huán)中氧急,不斷的取出消息捡鱼,處理消息八回,以此來驅(qū)動 Android 應用的運行。
2驾诈、Handler 的創(chuàng)建缠诅,Handler 的所有構(gòu)造方法都會跳轉(zhuǎn)到下面兩個之一
public Handler(Callback callback, boolean async) {
// Hanlder 是匿名類、內(nèi)部類乍迄、本地類時管引,如果沒有聲明為 static 則會出現(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());
}
}
// 獲取 Looper
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException("Can't create handler inside thread that has not called Looper.prepare()");
}
// 消息隊列,從 Looper 中獲取
mQueue = mLooper.mQueue;
// 處理消息的回調(diào)接口
mCallback = callback;
// 處理消息的方式是否為異步闯两,默認同步
mAsynchronous = async;
}
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
總結(jié):在 Handler 的構(gòu)造方法中褥伴,Handler 和 Looper谅将、MessageQueue 綁定起來,如果當前線程沒有 Looper 拋出異常(這也是為什么直接在子線程創(chuàng)建 Handler 會出現(xiàn)異常)重慢。
3饥臂、使用 Handler 發(fā)送消息
-> sendMessageAtTime(Message msg, long uptimeMillis)
// 除了 sendMessageAtFrontOfQueue,Handler 所有的 post似踱、sendMessage 都會跳到這個方法
// Message msg: 要發(fā)送的消息
// long uptimeMillis: 發(fā)送消息的絕對時間隅熙,通過 SystemClock.uptimeMillis() 加上我們自己的延遲時間 delayMillis 計算而來
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
// 消息隊列為空(可能已經(jīng)退出)返回 false 入隊失敗
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);
}
-> sendMessageAtFrontOfQueue(Message msg)
// 發(fā)送消息到 MessageQueeu 的隊頭
public final boolean sendMessageAtFrontOfQueue(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;
}
// 通過設(shè)置 uptimeMillis 為 0,是消息加入到 MessageQueue 的隊頭
return enqueueMessage(queue, msg, 0);
}
-> enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)
// 所有 Handler 的 post 屯援、sendMessage 系列方法和 runOnUiThread 最終都會調(diào)用這個方法
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
// msg.target 是一個 Handler猛们,將 Message 和 Handler 綁定
// 也就是用哪個 Handler 發(fā)送消息,這個 Message 就和哪個 Handler 綁定
msg.target = this;
// 如果設(shè)置了消息處理方式為異步處理
if (mAsynchronous) {
msg.setAsynchronous(true);
}
// MessageQueue 的方法狞洋,將消息入隊
return queue.enqueueMessage(msg, uptimeMillis);
}
-> MessageQueue#enqueueMessage(Message msg, long when)
boolean enqueueMessage(Message msg, long when) {
// Messgae 沒有綁定 Handler 拋出異常
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
// Messgae 正在使用 拋出異常
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
// 消息隊列正在退出弯淘,回收 Message
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(); // 調(diào)用 Message#recycleUnchecked()
return false;
}
msg.markInUse(); // 標記 Message 正在使用
msg.when = when; // 設(shè)置 Message 的觸發(fā)時間
// mMessages 記錄著 MessageQueue 的隊頭的消息
Message p = mMessages;
boolean needWake;
// MessageQueue 沒有消息、Message 觸發(fā)時間為 0吉懊、Messgae 觸發(fā)時間比隊頭 Message 早
// 總之這個 Message 在 MessageQueue 中需要最先被分發(fā)
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p; // 將以前的隊頭 Message 鏈接在這個 Message 后面
mMessages = msg; // 將這個 Message 賦值給 mMessages
needWake = mBlocked; // 隊列是否阻塞
} else {
// 標記隊列是否阻塞
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
// 按照時間順序?qū)?Message 插入消息隊列
for (;;) {
prev = p; // prev 記錄隊頭
p = p.next; // p 記錄隊頭的后一個
// 隊頭后面沒有消息或者其觸發(fā)事件比要插入的 Message 晚庐橙,跳出循環(huán)
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
// 將 Message 插入隊列
msg.next = p;
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
總結(jié):到現(xiàn)在為止,我們的 Handler 已經(jīng)將 Message 發(fā)送到了 MessageQueue借嗽,Message 靜靜的等待被處理态鳖。
4、Looper.loop() 還記得這個方法在 ActivityThread 的 main 調(diào)用了嗎恶导?正是它在不斷處理 MessageQueue 里面的消息浆竭。
public static void loop() {
// 獲取 Looper.Looper.prepare 準備好的 Looper
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
// 獲取 Looper 中的消息隊列
final MessageQueue queue = me.mQueue;
// 進入無線循環(huán)
for (;;) {
// 取出下一條消息
Message msg = queue.next();
// 沒有消息,退出 loop
// 其實上面 queue.next() 也是一個無限循環(huán)惨寿,獲取到消息就返回邦泄,沒有消息就一直循環(huán)
if (msg == null) {
return;
}
try {
// msg.target 實際上就是一個 Handler
// 獲取到了消息,使用綁定的 Handler#dispatchMessage 分發(fā)消息
msg.target.dispatchMessage(msg);
} finally {
}
// 釋放消息裂垦,把 Message 的各個變量清空然后放進消息池中
msg.recycleUnchecked();
}
}
5顺囊、Handler#dispatchMessage(msg) 消息是如何處理的
public void dispatchMessage(Message msg) {
// 1
if (msg.callback != null) {
handleCallback(msg);
} else {
// 2
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
// 3. 看到這個方法沒有!就是我們創(chuàng)建 Handler 時重寫的 handleMessage
// OK 整個流程打通蕉拢!
handleMessage(msg);
}
}
總結(jié):流程雖然通了特碳,但是處理 Message 的方法貌似有三種(我標記了序號),而且我們的 handleMessage 的優(yōu)先級最低晕换,其他方法會在什么情況下執(zhí)行呢午乓? 直接說結(jié)論了,調(diào)用 Handler 的 post 系列方法會走序號1的處理届巩,創(chuàng)建 Handler 傳入 Callback 會走序號2 的處理硅瞧。
Handler 機制總結(jié):想使用 Handler 必須要有 Looper,創(chuàng)建 Looper 的時候會創(chuàng)建 MessageQueue恕汇,在 Handler 的構(gòu)造的時候會綁定這個 Looper 和 MessageQueue腕唧,Handler 將 Message 發(fā)送到 MessageQueue 中,Looper.loop() 會不斷的從 MessageQueue 取出消息再交給這個 Handler 處理瘾英。
五. HandlerThread 的使用及源碼解讀
在子線程中能直接創(chuàng)建 Handler 嗎枣接?
new Thread(new Runnable() { @Override public void run() { new Handler().post(new Runnable() { @Override public void run() { MLog.i("Handler in " + Thread.currentThread().getName()); } }); } }).start();
答案前面提到了是不能,執(zhí)行上面的代碼會出現(xiàn) java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() 這個異常缺谴,異常提示我們但惶,不能再沒有調(diào)用 Looper.prepare() 的線程中創(chuàng)建 Handler。
-
簡單修改下代碼就可以了湿蛔,給線程準備好 Looper
new Thread(new Runnable() { @Override public void run() { // 準備一個 Looper膀曾,Looper 創(chuàng)建時對應的 MessageQueue 也會被創(chuàng)建 Looper.prepare(); // 創(chuàng)建 Handler 并 post 一個 Message 到 MessageQueue new Handler().post(new Runnable() { @Override public void run() { MLog.i("Handler in " + Thread.currentThread().getName()); } }); // Looper 開始不斷的從 MessageQueue 取出消息并再次交給 Handler 執(zhí)行 // 此時 Lopper 進入到一個無限循環(huán)中,后面的代碼都不會被執(zhí)行 Looper.loop(); } }).start();
- 上面的操作 Android 都幫我們封裝好了阳啥,正是 HandlerThread 這個類添谊。
HandlerThread 的簡單使用
// 1. 創(chuàng)建 HandlerThread
handlerThread = new HandlerThread("myHandlerThread") {
// onLooperPrepared 這個方法子線程執(zhí)行,由線程的 run 方法調(diào)用察迟,可以在里面直接創(chuàng)建 Handler
@Override protected void onLooperPrepared() {
super.onLooperPrepared();
new Handler().post(new Runnable() {
@Override public void run() {
// 注意:Handler 在子線程創(chuàng)建斩狱,這個方法也會運行在子線程,不可以更新 UI
MLog.i("Handler in " + Thread.currentThread().getName());
}
});
}
};
// 2. 準備 HandlerThread 的 Looper 并調(diào)用 onLooperPrepared
handlerThread.start();
// 3. 退出
@Override public void onDestroy() {
super.onDestroy();
handlerThread.quit();
}
// 也可以這樣用
// 1. 創(chuàng)建 HandlerThread 并準備 Looper
handlerThread = new HandlerThread("myHandlerThread");
handlerThread.start();
// 2. 創(chuàng)建 Handler 并綁定 handlerThread 的 Looper
new Handler(handlerThread.getLooper()).post(new Runnable() {
@Override public void run() {
// 注意:Handler 綁定了子線程的 Looper扎瓶,這個方法也會運行在子線程所踊,不可以更新 UI
MLog.i("Handler in " + Thread.currentThread().getName());
}
});
// 3. 退出
@Override public void onDestroy() {
super.onDestroy();
handlerThread.quit();
}
HandlerThread 源碼解讀
HandlerThread 繼承了 Thread,本質(zhì)是一個擁有 Looper 的線程概荷,因此在 HandlerThread 我們可以直接使用 Handler秕岛。
-
構(gòu)造方法
public HandlerThread(String name) { super(name); mPriority = Process.THREAD_PRIORITY_DEFAULT; } // 傳入線程的名稱和優(yōu)先級 // 注意 priority 的值必須來自 android.os.Process 不能來自 java.lang.Thread public HandlerThread(String name, int priority) { super(name); mPriority = priority; }
-
run 方法:創(chuàng)建子線程的 Looper
@Override public void run() { mTid = Process.myTid(); // 準備一個 Looper Looper.prepare(); synchronized (this) { // 獲取 Looper mLooper = Looper.myLooper(); // Looper 獲取成功后,喚醒 getLooper 的 wait notifyAll(); } Process.setThreadPriority(mPriority); // Looper 準備好的回調(diào)误证,在這個方法里可以使用 Handler 了 onLooperPrepared(); // Looper 開始循環(huán)取消息 Looper.loop(); mTid = -1; }
-
getLooper 方法:獲取子線程的 Looper
public Looper getLooper() { // 線程沒有開始或者死亡继薛,返回 null if (!isAlive()) { return null; } // If the thread has been started, wait until the looper has been created. // Looper 的創(chuàng)建時在子線程完成的,而 getLooper 可能會在主線程調(diào)用 // 當 Looper 沒有創(chuàng)建完成時雷厂,使用 wait 阻塞等待 // 上面在 Looper 創(chuàng)建好后會 notifyAll 來喚醒 wait synchronized(this) { while (isAlive() && mLooper == null) { try { wait(); } catch (InterruptedException e) { } } } return mLooper; }
-
quit 和 quitSafely :結(jié)束 Looper 的運行
// quit quit() -> looper.quit() -> mQueue.quit(false); // quitSafely quitSafely() -> looper.quitSafely() -> mQueue.quit(true); // 這兩個方法最終都會調(diào)用到 MessageQueue 的 void quit(boolean safe) 方法 // 前者會直接移除 MessageQueue 中的所有消息惋增,然后終止 MessageQueue // 后者會將 MessageQueue 中已有消息處理完成后(不再接收新消息)終止 MessageQueue
六.參考文章
- Android API 25 源碼
- Android消息機制1-Handler(Java層)