1. 程式人生 > >Android的訊息機制(Handler、Looper、MessageQueue)

Android的訊息機制(Handler、Looper、MessageQueue)

注:本文原始碼基於Android7.0

先大概概括一下訊息機制:

這裡有三個角色,Handler、looper、MessageQueue。Handler負責發訊息和處理訊息,Looper負責從MessageQueue中取出訊息給Handler處理,MessageQueue則負責儲存Handler發過來的訊息。

這個機制主要是將一個任務切換到指定執行緒中執行,就像我們在子執行緒中更新UI介面,就可以用Handler。多說一句,特殊情況下子執行緒中也是可以更新UI的,具體可以看這篇文章,大概意思就是在ViewRootImpl未完全初始化之前更新Android 中子執行緒真的不能更新 UI 嗎?

我們從Handler的sendMessage方法入手開始分析:

public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);
    }
再看sendMessageDelayed方法
public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

再看sendMessageAtTime方法
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        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);
    }
最後我們看enqueueMessage方法
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }
從最後一行我們可以看出,Handler的sendMessage方法最終就是往MessageQueue裡插入一條訊息。

Looper我們就從Looper.prepare方法來分析

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));
    }
prepare方法是為當前執行緒建立一個looper,從那個if語句中我們也知道了為什麼一個執行緒中只能有一個Looper。sThreadlocal是Threadlocal型別,是一個執行緒內部的資料儲存類,在該執行緒儲存的資料只能在該執行緒中獲取。

接下來我們看Looper.loop方法

public static void loop() {
	//獲取到當前的Looper
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
	//從Looper中得到MessageQueue
        final MessageQueue queue = me.mQueue;

        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

	//不斷的從MessageQueue取訊息,當沒有訊息時,next方法會阻塞,直到訊息佇列被標記為退出
	//這樣next方法會返回null
        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            // This must be in a local variable, in case a UI event sets the logger
            final Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

            final long traceTag = me.mTraceTag;
            if (traceTag != 0) {
                Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
            }
		//從這裡看到了Handler的訊息最終交給它的dispatchMessage方法來處理了
            try {
                msg.target.dispatchMessage(msg);
            } finally {
                if (traceTag != 0) {
                    Trace.traceEnd(traceTag);
                }
            }

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }

            msg.recycleUnchecked();
        }
    }


推薦一個公眾號,不吐槽,不毒舌,偶爾發發文章,偶爾推薦好物,歡迎關注





相關推薦

Android訊息機制HandlerMessageQueueLooper三者的工作原理

Android的訊息機制主要是指Handler的執行機制以及Handler所附帶的MessageQueue和Looper的工作過程。messagequeue意思是訊息佇列,它內部儲存一組訊息,有插入和刪除的功能,其實內部是以單鏈表的形式來實現佇列功能的。looper的意思是迴圈,它的主要功能是迴

Android訊息機制HandlerMessageQueueLooper詳細介紹

Android的訊息機制其實在android的開發過程中指的也就是Handler的執行機制,這也就引出了android中常見的面試問題: 簡述Handler、Looper、MessageQueue的含義,以及它們之間的關係 簡述Handler的執行機制 說明

Android訊息機制HandlerLooperMessageQueue

注:本文原始碼基於Android7.0先大概概括一下訊息機制:這裡有三個角色,Handler、looper、MessageQueue。Handler負責發訊息和處理訊息,Looper負責從MessageQueue中取出訊息給Handler處理,MessageQueue則負責儲

Android 訊息機制HandlerMessageQueueLooper

在這篇文章中,我們將會討論 Android 的訊息機制。提到 Handler,有過一些 Android 開發經驗的都應該很清楚它的作用,通常我們使用它來通知主執行緒更新 UI。但是 Handler 需要底層的 MessageQueue 和 Looper 來支援才能運作。這篇文章中,我們將會討論它們三個之間的關

深入理解android訊息機制——handler Looper原始碼

android 重要核心知識點,怎麼深刻理解都不為過,本篇部落格從常用api ,Looper Hanldery以及HanlderTread原始碼角度解讀 一 常用api,主執行緒接收處理訊息 private Handler handler = ne

Android訊息機制之 ThreadLocal

前言   今天重溫了Android開發藝術探索上的訊息機制,花了一些時間,書上寫很好,但是可能文章一些先後順序問題,不是特別好理解,這篇文章博主用了自己的理解,看原始碼,結合書上的知識,希望大家能更容易理解。(可能會寫的不太好。。。不正確的地方歡迎指出)  

Android訊息處理機制Hanlder機制HandlerLooperMessageQueue和Message

·前言長久以來,我使用Hanlder僅限於它的基本使用:post 和 sendMessage而對於Hanlder的原理和訊息處理機制並不清楚。找了兩篇比較深入的部落格:學習了一下,又對照了原始碼,小有收穫,俗話說“好記性不如爛筆頭”,所以做一下筆記,總結一下,方便以後回顧。·

Android訊息機制LooperHandlerMessageQueen

Android訊息機制之Looper、Handler、MessageQueen 本篇文章包括以下內容: 前言 Android訊息機制的簡介 Android訊息機制的使用 Android訊息機制的相關概念 Android訊息機制的通訊流程

Android訊息機制分析:HandlerLooperMessageQueue原始碼分析

1.前言 關於Handler訊息機制的部落格實際上是非常多的了。 之前也是看別人的部落格過來的,但是過了一段時間之後,一些細節也就忘了。 所以,就自己擼一篇,權當筆記,方便以後翻閱。 這篇文章主要是分析Handler訊息機制原理以及收集一些面試題來講解,

Android中的HandlerLooperMessageQueue的使用以及原理

       提到Handler大家一定都不陌生,通常我們都是在子執行緒通過在主執行緒中建立的Handler物件切換到主執行緒中去更新View的顯示內容,然而很少接觸Looper更沒有感覺到MessageQueue的存在,然而三者是密切相關的,那麼接下來分別介

android HandlerLooperMesssageMessageQueue原始碼解析

Handler:傳送和接收訊息 Looper:訊息(迴圈)輪詢器 Message:訊息池 MessageQueue:訊息佇列。雖然名為佇列,但事實上它的內部儲存結構並不是真正的佇列,而是採用單鏈表的資料結構來儲存訊息列表的 先來看Handler,其實系統很多東西都是通過Handler訊息

Android Thread Task Looper Handler 和 Message 等概念(草稿版,待寫)

(待寫文章,點開的直接關閉吧)     參考 https://huaonline.iteye.com/blog/1319627               &nb

Android訊息機制原理,仿寫Handler Looper原始碼解析跨執行緒通訊原理--之仿寫模擬Handler(四)

前篇總結:上一篇實現了用Looper管理訊息佇列和訊息迴圈,但是訊息的傳送和訊息處理都是在Looper中進行的。寫一個子執行緒使用這樣的Looper怎麼才能獲取到loop()死迴圈訊息佇列取出的訊息呢?用回撥!callBack! 第四節 仿寫Handler來發送訊息,實現回

Android訊息機制原理,仿寫Handler Looper原始碼跨執行緒通訊原理--之執行緒間通訊原理(一)

前言:我們都知道Android的執行緒通訊是用Handler、Looper機制實現的,面試也經常問道,網上也有很多文章介紹原始碼但是可能很多小白只是機械是的記憶,回答不清楚原理究竟是怎麼回事。下邊我將一步一步仿寫一個Handler、Looper模擬Android的執行緒間通訊

Android Handler 訊息機制解惑篇

Android中的訊息處理機制概述 大家對於Android中的訊息處理機制的用法一定都比較熟悉,至於工作原理估計不少人有研究。就像我們自己寫的類我們用起來比較熟悉一樣,如果我們熟悉了訊息處理機制的具體實現,那麼我們用起來肯定也會事半功倍。 博主之前只是稍有涉

Android 安全機制1uid gid 與 pid

1、概述        Android 安全機制來源於Linux,並且以Linux許可權管理為基礎,要了解Android的安全機制,需要從linux中的安全機制瞭解開始,而使用者的許可權管理又是linux安全機制的最基本的一個組成. Android的創新之處是在linux使

Android訊息機制-Handler

Android為了執行緒安全,不允許我們在UI執行緒外(即主執行緒外的子執行緒)操作UI。 1. 子執行緒為啥不能操作UI呢? 試想一下,如果多個執行緒都可以操作UI,不同執行緒都可以控制同一個UI,那麼勢必會出現執行緒安全問題。執行緒A在修改UI的同事,執行緒B也在改同一

Handler.post(Runnable r)再一次梳理Android訊息機制以及handler的記憶體洩露

Handler 每個初學Android開發的都繞不開Handler這個“坎”,為什麼說是個坎呢,首先這是Android架構的精髓之一,其次大部分人都是知其然卻不知其所以然。今天看到Handler.post這個方法之後決定再去翻翻原始碼梳理一下Handler

Android訊息機制Handler解析原始碼+Demo

新建了一個qq群 482543750,歡迎一起學習Android的小夥伴加入。 提供各種Android學習資料,面試資料,Android簡歷模板。 Handler是開發人員在面試過程中最常見的問題之一了,這篇文章將較為全面地對Handler進行解讀,包括原始碼層,

Android開發藝術探索》讀書筆記——Handler訊息機制ThreadLocal

ThreadLocal ThreadLocal是一個執行緒內部的資料儲存類。它可以為各執行緒儲存資料,同時只能由當前執行緒獲取到儲存的資料,對於其他執行緒來說則獲取不到。它可以在不同執行緒中維護一套資料的副本,並且彼此互不干擾。 一言不合上程式碼: privat