1. 程式人生 > >深入理解Android非同步訊息處理機制

深入理解Android非同步訊息處理機制

一。概述

  Android 中的非同步訊息處理主要分為四個部分組成,Message、Hndler、MessageQueue 和 Looper。其關係如下圖所示:

 

  1. Message 是執行緒之間傳遞的訊息,它可以在內部攜帶少量資訊,用於在不同執行緒之間交換資料。

  2. MessageQueue 是訊息佇列,它主要用於存放所有由 Handler 傳送過來的訊息,這部分訊息會一直在訊息佇列中,等待被處理。每個執行緒中只會有一個 MessageQueue 物件。

  3. Handler 是處理者,它主要用於傳送和處理訊息。 傳送訊息一般使用 handler  的 sendMessage()方法,處理訊息會呼叫 handleMessage() 方法。

  4. Looper 是每個執行緒中 MessageQueue 的管家, 呼叫 loop() 方法後,就會進入到一個無限迴圈當中,然後每當發現 MessageQueue 中存在一條訊息,就會將其取出,並傳遞到 handleMessage

()方法當中。每個執行緒中也只會有一個Looper物件。

二。詳細介紹

1、Looper

  對於Looper主要是prepare()和loop()兩個方法。

public static final void prepare() {  
        if (sThreadLocal.get() != null) {  
            
throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(true)); }

  sThreadLocal是一個ThreadLocal物件,可以在一個執行緒中儲存變數。Looper 就是儲存在sThreadLocal裡面。這個方法被呼叫後,首先會判斷當前執行緒裡面有沒有 Looper物件,如果沒有就會建立一  

個  Looper 物件,如果存在則會丟擲異常。可見,prepare()方法,不能被呼叫兩次。這就保證了一個執行緒只有一個Looper物件。

  接下來我們看一下Looper的建構函式:

private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mRun = true;
        mThread = Thread.currentThread();
}

  在 Looper 的建構函式中,建立了 MessageQueue 物件,這也保證了一個執行緒只有一個 MessageQueue 物件。

  然後我們看看 loop() 方法:

public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        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();

        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
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

            msg.target.dispatchMessage(msg);

            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.recycle();
        }
}

  這個方法先呼叫 myLooper() 方法,得到 sThreadLocal 中儲存的 Looper 物件,並得到 looper 物件對應的 MessageQueue 物件,然後就進入無限迴圈。

  該迴圈主要包括:取出一條訊息,如果沒有訊息則阻塞; 呼叫  msg.target.dispatchMessage(msg);把訊息交給msg的target的dispatchMessage方法去處理。

  Looper主要作用:

  1、 與當前執行緒繫結,保證一個執行緒只會有一個Looper例項,同時一個Looper例項也只有一個MessageQueue。
  

  2、 loop()方法,不斷從MessageQueue中去取訊息,交給訊息的target屬性的dispatchMessage去處理。

2、Handler

  在使用Handler之前,我們都是初始化一個例項,比如用於更新UI執行緒,我們會在宣告的時候直接初始化,或者在onCreate中初始化Handler例項。

private Handler mHandler = new Handler()
    {
        public void handleMessage(android.os.Message msg)
        {
            switch (msg.what)
            {
            case value:
                
                break;

            default:
                break;
            }
        };
    };

三。小結

  1、首先Looper.prepare()在本執行緒中儲存一個Looper例項,然後該例項中儲存一個MessageQueue物件;因為Looper.prepare()在一個執行緒中只能呼叫一次,所以MessageQueue在一個執行緒中只會

存在一個。大家可能還會問,那麼在Activity中,我們並沒有顯示的呼叫Looper.prepare()和Looper.loop()方法,為啥Handler可以成功建立呢,這是因為在Activity的啟動程式碼中,已經在當前UI執行緒呼叫

了Looper.prepare()和Looper.loop()方法

  2、Looper.loop()會讓當前執行緒進入一個無限迴圈,不端從MessageQueue的例項中讀取訊息,然後回撥msg.target.dispatchMessage(msg)方法。

  3、Handler的構造方法,會首先得到當前執行緒中儲存的Looper例項,並與Looper例項中的MessageQueue相關聯。

  4、Handler的sendMessage方法,會給msg的target賦值為handler自身,然後加入MessageQueue中。

  5、在構造Handler例項時,我們會重寫handleMessage方法,也就是msg.target.dispatchMessage(msg)最終呼叫的方法。

相關推薦

深入理解Android非同步訊息處理機制

一。概述   Android 中的非同步訊息處理主要分為四個部分組成,Message、Hndler、MessageQueue 和 Looper。其關係如下圖所示:     1. Message 是執行緒之間傳遞的訊息,它可以在內部攜帶少量資訊,用於在不同執行緒之間交換資料。   2. Messag

(轉載)Android 非同步訊息處理機制 讓你深入理解 Looper、Handler、Message三者關係

很多人面試肯定都被問到過,請問Android中的Looper , Handler , Message有什麼關係?本篇部落格目的首先為大家從原始碼角度介紹3者關係,然後給出一個容易記憶的結論。 1、 概述 Handler 、 Looper 、Message

Android 非同步訊息處理機制 讓你深入理解 Looper、Handler、Message三者關係

很多人面試肯定都被問到過,請問Android中的Looper , Handler , Message有什麼關係?本篇部落格目的首先為大家從原始碼角度介紹3者關係,然後給出一個容易記憶的結論。1、 概述Handler 、 Looper 、Message 這三者都與Android

android 非同步訊息處理機制 — AHandler

1. 引入 ALooper、AHandler、AMessage 在 android multimedia stagefright 的框架程式碼中,通篇都是這幾個類的身影,所以熟悉 android 多媒體框架的第一步必須理解這幾個類的含義。 這幾個類是為了實現非同步訊息機制而設計的

Android非同步訊息處理機制詳解及原始碼分析

PS一句:最終還是選擇CSDN來整理髮表這幾年的知識點,該文章平行遷移到CSDN。因為CSDN也支援MarkDown語法了,牛逼啊! 【工匠若水 http://blog.csdn.net/yanbober 轉載煩請註明出處,尊重分享成果】 最近相對來說比較閒,加上養病,所

Android非同步訊息處理機制:Looper、Handler、Message

1 簡介 Handler,Looper,Message這三者都與Android非同步訊息處理執行緒相關, Looper:負責建立一個MessageQueue,然後進入一個無限迴圈體不斷從該MessageQueue中讀取訊息; Handler:訊息建立者,一個或者多個

android非同步訊息處理機制

 android非同步訊息處理主要由四部分組成:Handler,Looper,Message,MessageQueue​ Message:執行緒之間傳遞的訊息,可以在內部攜帶少量訊息 MessageQueue: Looper:每個執行緒有且最多隻能有一個Looper物件

Android非同步訊息處理機制的原始碼分析

1、背景 相信做過一段時間的Android開發都瞭解,當我們在子執行緒中更新UI時會丟擲異常,導致程式崩潰,Android4.0之後只允許在UI執行緒中更新介面,但是我們也不能再UI執行緒中處理耗時操作,那樣會導致應用程式無響應(即出現ANR)。 那如果想解

Android非同步訊息處理機制 handler

我們都知道,Android UI是執行緒不安全的,如果在子執行緒中嘗試進行UI操作,程式就有可能會崩潰。相信大家在日常的工作當中都會經常遇到這個問題,解決的方案應該也是早已爛熟於心,即建立一個Message物件,然後藉助Handler傳送出去,之後在Handler的han

Android非同步訊息處理機制原始碼分析

宣告:本文是參考了以下幾位大神的文章,自己按照自己的思維習慣整理的筆記,並新增一些相關的內容。如有不正確的地方歡迎留言指出,謝謝! 郭霖部落格 鴻洋部落格 任玉剛《Android開發藝術探索》 一. Andoid訊息機制概述

Android 非同步訊息處理機制解析

一、Message、Handler、MessageQueue、Looper   Android 中的非同步訊息處理主要由四個部分組成,Message、Handler、MessageQueue、Looper。   1. Message: Message 是線上

Android非同步訊息處理機制學習筆記

(一)Handler 什麼是Handler Android訊息機制的上層介面,Handler通過傳送和處理Message和Runnable物件來關聯相對應執行緒的MessageQueeu. 可

Android非同步訊息處理機制詳解

關於Handler例項化的一些關鍵資訊,具體如下: 在主執行緒中可以直接建立Handler物件,而在子執行緒中需要先呼叫Looper.prepare()才能建立Handler物件,否則執行丟擲”

Android非同步訊息處理機制Handler

很多人第一次接觸Handler可能是因為一句話”子執行緒不能操作ui”,那子執行緒能不能操作ui呢?我們在這裡不多討論(其實是可以的,但是執行緒不安全),我們來分析下handler是如何運轉起來的。 一般用法都是在“主執行緒”中new一個handler

Android Handler 非同步訊息處理機制的妙用 建立強大的圖片載入類

                最近建立了一個群,方便大家交流,群號:55032675上一篇部落格介紹了Android非同步訊息處理機制,如果你還不瞭解,可以看:Android 非同步訊息處理機制 讓你深入理解 Looper、Handler、Message三者關係 。那篇部落格的最後,提出可以把非同步訊息處理

Android中的非同步訊息處理機制

這也是Android中老生常談的一個話題了,它本身並不是很複雜,可是面試官比較喜歡問。本文就從原始碼再簡單的理一下這個機制。也可以說是理一下Handler、Looper、MessageQueue之間的關係。 單執行緒中的訊息處理機制的實現 首先我們以Looper.java原始碼中給出的一個例子來

Android非同步訊息處理機制詳解

一、在子執行緒中更新UI概述 和許多其他的GUI 庫一樣,Android 的UI 也是執行緒不安全的。也就是說,如果想要更新應用程式裡的UI 元素,則必須在主執行緒中進行,否則就會出現異常。但是有些時候,我們必須在子執行緒裡去執行一些耗時任務,然後根據任務的執

Android Handler 非同步訊息處理機制三:妙用手法 建立強大的圖片載入類

上一篇部落格介紹了Android非同步訊息處理機制,如果你還不瞭解,可以看:Android 非同步訊息處理機制 讓你深入理解 Looper、Handler、Message三者關係 。那篇部落格的最後,提出可以把非同步訊息處理機制不僅僅是在MainActivit

android非同步訊息處理機制及Handler

這時就需要Handler了,修改MainActivity如下:public class MainActivity extends AppCompatActivity { public static final int UPDATE_TEXT =1 ; @Override protec