Android任務(wù)管理機(jī)制

概述

消息機(jī)制涉及MessageQueue/Message/Looper/Handler這4個(gè)類。

說(shuō)明
  • Message:消息分為硬件產(chǎn)生的消息(如按鈕、觸摸)和軟件生成的消息;,Message有自己的緩存池,避免message的頻繁創(chuàng)建銷毀
  • MessageQueue:消息隊(duì)列的主要功能向消息池投遞消息(MessageQueue.enqueueMessage)和取走消息池的消息(MessageQueue.next);
  • Handler:消息輔助類,主要功能向消息池發(fā)送各種消息事件(Handler.sendMessage)和處理相應(yīng)消息事件(Handler.handleMessage);
  • Looper:不斷循環(huán)執(zhí)行(Looper.loop),按分發(fā)機(jī)制將消息分發(fā)給目標(biāo)處理者。
類關(guān)系
  • Looper有一個(gè)MessageQueue消息隊(duì)列;
  • MessageQueue有一組待處理的Message;
  • Message中有一個(gè)用于處理消息的Handler;
  • Handler中有Looper和MessageQueue;
ThreadLocal
  • 線程本地存儲(chǔ)區(qū)(Thread Local Storage,簡(jiǎn)稱為TLS),每個(gè)線程都有自己的私有的本地存儲(chǔ)區(qū)域,不同線程之間彼此不能訪問對(duì)方的TLS區(qū)域。
  • 每個(gè)線程可以有多個(gè)TLS,一個(gè)TLS對(duì)應(yīng)一個(gè)value
  • Looper 創(chuàng)建就以TLS方式創(chuàng)建,一個(gè)線程中最多只能有1個(gè)Looper
主線程驅(qū)動(dòng)
  • 主線程最終就是調(diào)用Looper的loop方法進(jìn)入死循環(huán),進(jìn)行消息驅(qū)動(dòng)
  • 主線程的Looper 是在 ActivityThread main函數(shù)中創(chuàng)建的
public static void main(String[] args) {
        // Install selective syscall interception
        AndroidOs.install();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

        Environment.initForCurrentUser();

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        Process.setArgV0("<pre-initialized>");

        Looper.prepareMainLooper();

        // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
        // It will be in the format "seq=114"
        long startSeq = 0;
        if (args != null) {
            for (int i = args.length - 1; i >= 0; --i) {
                if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                    startSeq = Long.parseLong(
                            args[i].substring(PROC_START_SEQ_IDENT.length()));
                }
            }
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
  • 消息生產(chǎn)
    • handler::enqueueMessage,MessageQueue是按照Message觸發(fā)時(shí)間的先后順序排列的,隊(duì)頭的消息是將要最早觸發(fā)的消息。當(dāng)有消息需要加入消息隊(duì)列時(shí),會(huì)從隊(duì)列頭開始遍歷,直到找到消息應(yīng)該插入的合適位置,以保證所有消息的時(shí)間順序。
  • 消息消費(fèi)(在loop中)
    • 讀取MessageQueue的下一條Message;
Message next() {
    final long ptr = mPtr;
    if (ptr == 0) { //當(dāng)消息循環(huán)已經(jīng)退出,則直接返回
        return null;
    }
    int pendingIdleHandlerCount = -1; // 循環(huán)迭代的首次為-1
    int nextPollTimeoutMillis = 0;
    for (;;) {
        if (nextPollTimeoutMillis != 0) {
            Binder.flushPendingCommands();
        }
        //nativePollOnce是阻塞操作,其中nextPollTimeoutMillis代表下一個(gè)消息到來(lái)前,還需要等待的時(shí)長(zhǎng);當(dāng)nextPollTimeoutMillis = -1時(shí),表示消息隊(duì)列中無(wú)消息,會(huì)一直等待下去。
        nativePollOnce(ptr, nextPollTimeoutMillis);
        synchronized (this) {
            final long now = SystemClock.uptimeMillis();
            Message prevMsg = null;
            Message msg = mMessages;
            //當(dāng)消息的Handler為空時(shí),則查詢異步消息
            if (msg != null && msg.target == null) {
                //當(dāng)查詢到異步消息,則立刻退出循環(huán)
                do {
                    prevMsg = msg;
                    msg = msg.next;
                } while (msg != null && !msg.isAsynchronous());
            }
            if (msg != null) {
                if (now < msg.when) {
                    //當(dāng)異步消息觸發(fā)時(shí)間大于當(dāng)前時(shí)間,則設(shè)置下一次輪詢的超時(shí)時(shí)長(zhǎng)
                    nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
                } else {
                    // 獲取一條消息,并返回
                    mBlocked = false;
                    if (prevMsg != null) {
                        prevMsg.next = msg.next;
                    } else {
                        mMessages = msg.next;
                    }
                    msg.next = null;
                    //設(shè)置消息的使用狀態(tài),即flags |= FLAG_IN_USE
                    msg.markInUse();
                    return msg;   //成功地獲取MessageQueue中的下一條即將要執(zhí)行的消息
                }
            } else {
                //沒有消息
                nextPollTimeoutMillis = -1;
            }
            //消息正在退出,返回null
            if (mQuitting) {
                dispose();
                return null;
            }
            //當(dāng)消息隊(duì)列為空,或者是消息隊(duì)列的第一個(gè)消息時(shí)
            if (pendingIdleHandlerCount < 0 && (mMessages == null || now < mMessages.when)) {
                pendingIdleHandlerCount = mIdleHandlers.size();
            }
            if (pendingIdleHandlerCount <= 0) {
                //沒有idle handlers 需要運(yùn)行,則循環(huán)并等待。
                mBlocked = true;
                continue;
            }
            if (mPendingIdleHandlers == null) {
                mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
            }
            mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
        }
        //只有第一次循環(huán)時(shí),會(huì)運(yùn)行idle handlers,執(zhí)行完成后,重置pendingIdleHandlerCount為0.
        for (int i = 0; i < pendingIdleHandlerCount; i++) {
            final IdleHandler idler = mPendingIdleHandlers[i];
            mPendingIdleHandlers[i] = null; //去掉handler的引用
            boolean keep = false;
            try {
                keep = idler.queueIdle();  //idle時(shí)執(zhí)行的方法
            } catch (Throwable t) {
                Log.wtf(TAG, "IdleHandler threw exception", t);
            }
            if (!keep) {
                synchronized (this) {
                    mIdleHandlers.remove(idler);
                }
            }
        }
        //重置idle handler個(gè)數(shù)為0,以保證不會(huì)再次重復(fù)運(yùn)行
        pendingIdleHandlerCount = 0;
        //當(dāng)調(diào)用一個(gè)空閑handler時(shí),一個(gè)新message能夠被分發(fā),因此無(wú)需等待可以直接查詢pending message.
        nextPollTimeoutMillis = 0;
    }
}
  • 把Message分發(fā)給相應(yīng)的target;
  • 再把分發(fā)后的Message回收到消息池,以便重復(fù)利用。
IdleHandler

每次在獲取下一個(gè)message時(shí),沒有獲取到時(shí)執(zhí)行idleHnalder的runable

整體流程
handler_java.jpg
  • Handler通過(guò)sendMessage()發(fā)送Message到MessageQueue隊(duì)列;
  • Looper通過(guò)loop(),不斷提取出達(dá)到觸發(fā)條件的Message,并將Message交給target來(lái)處理;
  • 經(jīng)過(guò)dispatchMessage()后,交回給Handler的handleMessage()來(lái)進(jìn)行相應(yīng)地處理。
  • 將Message加入MessageQueue時(shí),處往管道寫入字符,可以會(huì)喚醒loop線程;如果MessageQueue中沒有Message,并處于Idle狀態(tài),則會(huì)執(zhí)行IdelHandler接口中的方法,往往用于做一些清理性地工作。

Native 層 消息機(jī)制

在整個(gè)消息機(jī)制中,而MessageQueue是連接Java層和Native層的紐帶,換言之,Java層可以向MessageQueue消息隊(duì)列中添加消息,Native層也可以向MessageQueue消息隊(duì)列中添加消息,接下來(lái)來(lái)看看MessageQueue。


handler_arch.png
  • 紅色虛線關(guān)系:Java層和Native層的MessageQueue通過(guò)JNI建立關(guān)聯(lián),彼此之間能相互調(diào)用,搞明白這個(gè)互調(diào)關(guān)系,也就搞明白了Java如何調(diào)用C++代碼,C++代碼又是如何調(diào)用Java代碼。
  • 藍(lán)色虛線關(guān)系:Handler/Looper/Message這三大類Java層與Native層并沒有任何的真正關(guān)聯(lián),只是分別在Java層和Native層的handler消息模型中具有相似的功能。都是彼此獨(dú)立的,各自實(shí)現(xiàn)相應(yīng)的邏輯。
  • WeakMessageHandler繼承于MessageHandler類,NativeMessageQueue繼承于MessageQueue類

MessageQueue通過(guò)mPtr變量保存NativeMessageQueue對(duì)象,從而使得MessageQueue成為Java層和Native層的樞紐,既能處理上層消息,也能處理native層消息;下面列舉Java層與Native層的對(duì)應(yīng)圖

另外,消息處理流程是先處理Native Message,再處理Native Request,最后處理Java Message。理解了該流程,也就明白有時(shí)上層消息很少,但響應(yīng)時(shí)間卻較長(zhǎng)的真正原因。

  • Native Message:和java層類似,由native的
  • Native Request: 由fd觸發(fā)的event,這些文件描述符可以讓其他組件注冊(cè),發(fā)送

refrence

http://www.itdecent.cn/p/f7cabfe19720
Android Handler 通信 - 徹底了解 Handler 的通信過(guò)程

Android Handler:手把手帶你深入分析 Handler機(jī)制源碼

?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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