Handler系列--Handler源碼簡(jiǎn)析

前言

本系列文章,將分享與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)作流程

Handler運(yùn)作流程.png

可以看到,整個(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

Handler系列--Looper簡(jiǎn)析

  • MessageQueue

Handler系列--MessageQueue

  • Message

Handler系列--Message簡(jiǎn)析

本篇內(nèi)容到此結(jié)束,感謝收看~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容