前言
本系列文章,將分享與Handler相關(guān)的知識(shí),包括Handler的結(jié)構(gòu),運(yùn)作流程,各個(gè)類(lèi)的作用、之間的關(guān)系
內(nèi)容提要
本篇文章將簡(jiǎn)析Handler的作用,運(yùn)作流程,以及主要方法
Handler簡(jiǎn)介
Handler是Android SDK來(lái)處理異步消息的核心類(lèi)。
子線(xiàn)程與主線(xiàn)程通過(guò)Handler來(lái)進(jìn)行通信。子線(xiàn)程可以通過(guò)Handler來(lái)通知主線(xiàn)程進(jìn)行UI更新。
引用自--《Handler的作用與用法》
為什么需要子線(xiàn)程通知主線(xiàn)程更新UI呢?
眾所周知,主線(xiàn)程不能進(jìn)行耗時(shí)操作,子線(xiàn)程不能更新UI。那么普遍存在這么一種場(chǎng)景:主線(xiàn)程開(kāi)啟子線(xiàn)程,進(jìn)行耗時(shí)操作(獲取網(wǎng)絡(luò)數(shù)據(jù)、做大量數(shù)據(jù)的存取、壓縮圖片等等),完成以后,將結(jié)果給回主線(xiàn)程,進(jìn)行UI的更新。Handler的作用即體現(xiàn)于此,用作多個(gè)線(xiàn)程之間的橋梁
Handler用法
請(qǐng)自行百度、Google
Handler運(yùn)作流程

可以看到,整個(gè)過(guò)程中
- 1.Handler充當(dāng)了收發(fā)器的角色,負(fù)責(zé)發(fā)送Msg,接收到期的Msg并在UI線(xiàn)程做響應(yīng)
- 2.Message作為信息媒介,傳遞數(shù)據(jù)
- 3.Looper作為橋梁和調(diào)度者,負(fù)責(zé)切換線(xiàn)程,并讓Msg回調(diào)Handler(至于怎么做的線(xiàn)程切換,下面解答)
重要屬性
final Looper mLooper;
final MessageQueue mQueue;
//自定義的消息回調(diào)
final Callback mCallback;
//標(biāo)記是否為同步的Handler,Handler默認(rèn)都會(huì)被創(chuàng)建為同步的
final boolean mAsynchronous;
重要方法
public Handler(Callback callback, boolean async)
構(gòu)造方法之一
- 1.FIND_POTENTIAL_LEAKS內(nèi)的邏輯,就是判斷這個(gè)Handler的繼承類(lèi)是不是非靜態(tài)的 匿名/內(nèi)部/本地 類(lèi),從而提示你,你要新建的這個(gè)Handler,將有內(nèi)存泄漏的風(fēng)險(xiǎn)(但是源碼里面FIND_POTENTIAL_LEAKS是一個(gè)默認(rèn)為false的final值,所以其實(shí)不會(huì)幫我們檢測(cè),我們需要自己去避免內(nèi)存泄漏)
- 2.獲取當(dāng)前線(xiàn)程的Looper,及其持有的Queue
-
3.實(shí)際上,這是一個(gè)@hide的方法,我們并不能直接通過(guò)這個(gè)方法創(chuàng)建Handler,Handler支持以下幾個(gè)方法新建,你可以看到,都是設(shè)為同步的,也就是理論上說(shuō),我們沒(méi)法用這些構(gòu)造方法自己創(chuàng)建一個(gè)異步的Handler(實(shí)際上是異步的Message),當(dāng)然我們可以用反射來(lái)嘗試新建異步的Handler,但是不建議這樣做
public Handler(Callback callback, boolean async) {
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());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
public static Handler createAsync(@NonNull Looper looper, @NonNull Callback callback)
創(chuàng)建一個(gè)異步的Handler,本質(zhì)上也是調(diào)用的構(gòu)造方法。這里算是提供了一個(gè)構(gòu)建異步Handler的方法,但是是API>=28以上才能使用的,我手上沒(méi)有9.0的手機(jī),沒(méi)法嘗試
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis)
- 1.這個(gè)是sendMessage系列方法最終調(diào)用的方法
- 2.通過(guò)這里入列的消息,一定有target,這個(gè)信息在我們分析MessageQueue的時(shí)候會(huì)有用
- 3.這里會(huì)根據(jù)mAsynchronous來(lái)設(shè)置msg的同步異步,而根據(jù)前面的分析,API<28的時(shí)候,我們理論上無(wú)法創(chuàng)建一個(gè)異步的Handler,那么也就是說(shuō)msg必然是同步的,這個(gè)信息在我們分析MessageQueue的時(shí)候也會(huì)有用
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
public void dispatchMessage(Message msg)
- 1.這個(gè)方法就是最終消息到期,從消息隊(duì)列出列之后,handler回調(diào)消息的地方
- 2.如果自定義了Message的Callback,將不會(huì)走h(yuǎn)andleMessage()的邏輯
- 3.如果自定義了Handler的Callback,也可以不在handleMessage()方法里處理回調(diào)
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
private static void handleCallback(Message message) {
message.callback.run();
}
其他方法
obtainMessage系列方法
實(shí)際上是調(diào)用的Message的obtain系列方法,留在Message篇介紹吧
removeMessages系列方法
--public final void removeCallbacks(Runnable r)
--public final void removeCallbacks(Runnable r, Object token)
--public final void removeMessages(int what)
--public final void removeMessages(int what, Object object)
--public final void removeCallbacksAndMessages(Object token)
根據(jù)message的what/obj/handler/callback等移除message
hasMessages系列方法
--public final boolean hasMessages(int what)
--public final boolean hasMessagesOrCallbacks()
--public final boolean hasMessages(int what, Object object)
--public final boolean hasCallbacks(Runnable r)
通過(guò)what/obj/handler/callback等判斷消息隊(duì)列中是否有對(duì)應(yīng)的message
public final void dump(Printer pw, String prefix)
打印當(dāng)前的消息隊(duì)列信息
相關(guān)類(lèi)介紹
-
Looper
-
MessageQueue
-
Message
本篇內(nèi)容到此結(jié)束,感謝收看~~
