1. 程式人生 > >(轉載)Android 非同步訊息處理機制 讓你深入理解 Looper、Handler、Message三者關係

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

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

1、 概述

Handler 、 Looper 、Message 這三者都與Android非同步訊息處理執行緒相關的概念。那麼什麼叫非同步訊息處理執行緒呢?
非同步訊息處理執行緒啟動後會進入一個無限的迴圈體之中,每迴圈一次,從其內部的訊息佇列中取出一個訊息,然後回撥相應的訊息處理函式,執行完成一個訊息後則繼續迴圈。若訊息佇列為空,執行緒則會阻塞等待。

說了這一堆,那麼和Handler 、 Looper 、Message有啥關係?其實Looper負責的就是建立一個MessageQueue,然後進入一個無限迴圈體不斷從該MessageQueue中讀取訊息,而訊息的建立者就是一個或多個Handler 。

2、 原始碼解析

1、Looper

對於Looper主要是prepare()和loop()兩個方法。
首先看prepare()方法
  1. publicstaticfinalvoid prepare() {  
  2.         if (sThreadLocal.get() != null) {  
  3.             thrownew RuntimeException("Only one Looper may be created per thread");  
  4.         }  
  5.         sThreadLocal.set(new Looper(
    true));  
  6. }  

sThreadLocal是一個ThreadLocal物件,可以在一個執行緒中儲存變數。可以看到,在第5行,將一個Looper的例項放入了ThreadLocal,並且2-4行判斷了sThreadLocal是否為null,否則丟擲異常。這也就說明了Looper.prepare()方法不能被呼叫兩次,同時也保證了一個執行緒中只有一個Looper例項~相信有些哥們一定遇到這個錯誤。
下面看Looper的構造方法:
  1. private Looper(boolean quitAllowed) {  
  2.         mQueue = new MessageQueue(quitAllowed);  
  3.         mRun = true;  
  4.         mThread = Thread.currentThread();  
  5. }  
在構造方法中,建立了一個MessageQueue(訊息佇列)。
然後我們看loop()方法:
  1. publicstaticvoid loop() {  
  2.         final Looper me = myLooper();  
  3.         if (me == null) {  
  4.             thrownew RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");  
  5.         }  
  6.         final MessageQueue queue = me.mQueue;  
  7.         // Make sure the identity of this thread is that of the local process,
  8.         // and keep track of what that identity token actually is.
  9.         Binder.clearCallingIdentity();  
  10.         finallong ident = Binder.clearCallingIdentity();  
  11.         for (;;) {  
  12.             Message msg = queue.next(); // might block
  13.             if (msg == null) {  
  14.                 // No message indicates that the message queue is quitting.
  15.                 return;  
  16.             }  
  17.             // This must be in a local variable, in case a UI event sets the logger
  18.             Printer logging = me.mLogging;  
  19.             if (logging != null) {  
  20.                 logging.println(">>>>> Dispatching to " + msg.target + " " +  
  21.                         msg.callback + ": " + msg.what);  
  22.             }  
  23.             msg.target.dispatchMessage(msg);  
  24.             if (logging != null) {  
  25.                 logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);  
  26.             }  
  27.             // Make sure that during the course of dispatching the
  28.             // identity of the thread wasn't corrupted.
  29.             finallong newIdent = Binder.clearCallingIdentity();  
  30.             if (ident != newIdent) {  
  31.                 Log.wtf(TAG, "Thread identity changed from 0x"
  32.                         + Long.toHexString(ident) + " to 0x"
  33.                         + Long.toHexString(newIdent) + " while dispatching to "
  34.                         + msg.target.getClass().getName() + " "
  35.                         + msg.callback + " what=" + msg.what);  
  36.             }  
  37.             msg.recycle();  
  38.         }  
  39. }  

第2行:
public static Looper myLooper() {
return sThreadLocal.get();
}
方法直接返回了sThreadLocal儲存的Looper例項,如果me為null則丟擲異常,也就是說looper方法必須在prepare方法之後執行。
第6行:拿到該looper例項中的mQueue(訊息佇列)
13到45行:就進入了我們所說的無限迴圈。
14行:取出一條訊息,如果沒有訊息則阻塞。
27行:使用呼叫 msg.target.dispatchMessage(msg);把訊息交給msg的target的dispatchMessage方法去處理。Msg的target是什麼呢?其實就是handler物件,下面會進行分析。
44行:釋放訊息佔據的資源。

Looper主要作用:
1、 與當前執行緒繫結,保證一個執行緒只會有一個Looper例項,同時一個Looper例項也只有一個MessageQueue。
2、 loop()方法,不斷從MessageQueue中去取訊息,交給訊息的target屬性的dispatchMessage去處理。
好了,我們的非同步訊息處理執行緒已經有了訊息佇列(MessageQueue),也有了在無限迴圈體中取出訊息的哥們,現在缺的就是傳送訊息的物件了,於是乎:Handler登場了。

2、Handler

使用Handler之前,我們都是初始化一個例項,比如用於更新UI執行緒,我們會在宣告的時候直接初始化,或者在onCreate中初始化Handler例項。所以我們首先看Handler的構造方法,看其如何與MessageQueue聯絡上的,它在子執行緒中傳送的訊息(一般傳送訊息都在非UI執行緒)怎麼傳送到MessageQueue中的。
  1. public Handler() {  
  2.         this(nullfalse);  
  3. }  
  4. public Handler(Callback callback, boolean async) {  
  5.         if (FIND_POTENTIAL_LEAKS) {  
  6.             final Class<? extends Handler> klass = getClass();  
  7.             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&  
  8.                     (klass.getModifiers() & Modifier.STATIC) == 0) {  
  9.                 Log.w(TAG, "The following Handler class should be static or leaks might occur: " +  
  10.                     klass.getCanonicalName());  
  11.             }  
  12.         }  
  13.         mLooper = Looper.myLooper();  
  14.         if (mLooper == null) {  
  15.             thrownew RuntimeException(  
  16.                 "Can't create handler inside thread that has not called Looper.prepare()");  
  17.         }  
  18.         mQueue = mLooper.mQueue;  
  19.         mCallback = callback;  
  20.         mAsynchronous = async;  
  21.     }  

14行:通過Looper.myLooper()獲取了當前執行緒儲存的Looper例項,然後在19行又獲取了這個Looper例項中儲存的MessageQueue(訊息佇列),這樣就保證了handler的例項與我們Looper例項中MessageQueue關聯上了。

然後看我們最常用的sendMessage方法

  1. publicfinalboolean sendMessage(Message msg)  
  2.  {  
  3.      return sendMessageDelayed(msg, 0);  
  4.  }  

  1. publicfinalboolean sendEmptyMessageDelayed(int what, long delayMillis) {  
  2.      Message msg = Message.obtain();  
  3.      msg.what = what;  
  4.      return sendMessageDelayed(msg, delayMillis);  
  5.  }  

  1. public

    相關推薦

    (轉載)Android 非同步訊息處理機制 深入理解 LooperHandlerMessage三者關係

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

    Android 非同步訊息處理機制 深入理解 LooperHandlerMessage三者關係

    很多人面試肯定都被問到過,請問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非同步訊息處理機制:LooperHandlerMessage

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

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

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

    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