`
sd4886656
  • 浏览: 90351 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

[Android]android.os 源代码中的Looper,Handler,Message,MessageQueue

阅读更多

转自:http://milochen.wordpress.com/2011/03/25/understanding-android-os-src-looperhandler-message-messagequeue/

 

作者:Milochen

 

 

Hi All:
Handler, Message, Looper, MessageQueue 是 android.os 中的class
也是深度開發 Application 時,必須具備的基本觀念,若清楚了解,
便可運用的當。

因為網路有太多模糊不清的文章,大家說法看起來也都不太一樣,
很容易讓人猜東猜西,想東想西的。至於,不想瞎猜的話,就不如直接把source code都讀懂吧。

因此本篇文章,目地在於,快速引導大家快速「正確」的了解,重點在於「正確性」
並且透過靜態 trace code  的方式,跟大家解釋它 source code 的運作原理。

因此,對於四個 class沒信心的時候,
就直接將文章看下去,文章會完整交代 trace source code的部份。

關於這四個 class 的結論:

========================================================
整個Handler, Message, MessageQueue, Looper 它們四個 class 只有一個共同的目標
就是讓程式碼,可以丟到其它 thread 去執行。這麼作有什麼好處呢 ??

例如 android 的 GUI 元件是 thread safe的 (意思是,元件的使用,無法multi-thread執行)
Activity 的畫面顯示是由 UI Thread所負責的,若是你寫了 mutlti-thread 程式時
又想更新畫面,就必須要將 Thread 內部的一段程式碼,交由 UI Thread 來執行才行。

OK, 上面四個 class 的共同目地已經說明完畢了,那麼這四個 class有其分工方式。
因此每個 class 的設計又有不同目地。說明如下 …

Handler 的目地,在於提供 callback function,預其給其它 Thread 作執行
但Handler又要如何 transfer 至其它 Thread 呢 ?  於是有了 Message

Message 的目地,將 Handler 包裝起來,傳送給其它 Thread
但是同時有多條 thread 不斷的在系統中傳遞 Message 那麼如何緩衝呢 ?

MessageQueue 的目地,是為了讓 Message 能夠作緩衝,好讓Message先暫存起來。
因此,當Message 已經被放在其它 Thread上的MessageQueue 之後,
它裡面包著 Handler,而 Handler上的 callback function 總得有人來執行吧 ??

Looper 的目地 :
就是為了將 Message 由 Thread 所對應的 MessageQueue 取出來,並且拿出 Handler
來執行它上面的 callback function.

當 Looper.java 中的 loop() 被呼叫起來之後,它就是在反覆作這件事
不斷將Handler由Message拆包出來,並且執行Handler上的callback function。

                                                                                
======================================================================

以上,已經將這四個class的關係完整說明了。看到這邊您還有疑慮嗎 ?
接下來小弟就直接講 trace source 的部份,
教你快速 trace 懂這些 code,迅速驗證出這四個 class 的用途。

以下開始 trace source code .. Follow Me ^____^

Looper 中的 mThread, mQueue 只有在 Ctor 建立,並且”不會再更改”
mThread = Thread.currentThread() //紀綠此Looper由那條Thread建立
mQueue = new MessageQueue() //每個Looper只有唯一的Queue

主要的執行函式為
Looper.java: loop()  {
  MessageQueue queue = myLooper().mQueue //取得CurrentThread下Looper的MsgQueue
  while(true) {
    Message msg = queue.next() //跳到msg一個message
    msg.target.dispatchMessage(msg)
    //target 被almost設定的方式,是透過Message.obtain(Handler h)設 h 為target
    msg.recycle(); //In Message class, 只有recycle()與obtain() 作sync同步
  }
}

                                                                                
上面程式中,所提到的東西,在以下深入探討。

(1) dispatchMessage(msg) 是如何重要呢 ?
它呼叫 Handler 上的 handleMessage().
———————————————
PS: 一般來說,我們會寫個 EHandler extends Handler,
並且重寫handleMessage()function 好讓 Handler 上的 handlerMessage()
被 UI Thread呼叫,來更新畫面。
——————————

(2) 至於 loop() 是如何被使用的呢 ?
typical example 大約是這樣子的
class LooperThread extends Thread {
  public Handler mHandler;
  public void run() {
    Looper.prepare();
    mHandler = new Handler() {
      public void handleMessage(Message msg) {
        // process incoming messages here
      }
    };
    Looper.loop();
}

類似的 typical example 在 Android 系統中的 ActivityThread.java :: main()

public static final void main(String[] args) {
  Looper.prepareMainLooper();
  ActivityThread thread = new ActivityThread();
  Looper.loop();
}

                                                                                
額外話 …

此範例trace下去將發現, Looper.mMainLooper 變數被設定為
(Looper)sThreadLocal.get()

許多重要的 android source code 皆會透過 getMainLooper() 函數取出
Looper.mMainLooper

(3) msg.target 是個 Handler 類別,  又是從何而來的呢 ?

直接copy高煥堂網路文章中的example code過來 … 
講義摘錄之28:Anrdroid 的Message Queue(3/3) 的example code如下
class AnyClass implements Runnable {
 public void run() {
         Looper.prepare();
         h = new Handler(){
               public void handleMessage(Message msg) {
                  EventHandler ha = new EventHandler(Looper.getMainLooper());
                    String obj = (String)msg.obj + ”, myThread”;
                     Message m = ha.obtainMessage(1, 1, 1, obj);
                     ha.sendMessage(m); //sendMessage的原理,請見(4)的說明
         }
       };
  Looper.loop();
  }
}

                                                                                
我們直接由此來作解釋,
追蹤當中的 obtainMssage 可發現 target的由來。原理如下
Handler.java: Message obtainMessage(int what, int arg1, int arg2)
Message.java:
static Message obtain(Handler h, int what, int arg1, int arg2) {
        Message m = obtain();
        m.target = h;  // 這邊就是 msg.target 的由來
        m.what = what;
        m.arg1 = arg1;
        m.arg2 = arg2;
}

而 Message m = obtain() 是執行下面這段程式

    public static Message obtain() {
        synchronized (mPoolSync) { //與 recycle() 共用 mPoolSync
            if (mPool != null) {
                Message m = mPool;
                mPool = m.next;
                m.next = null;
                return m;
            }
        }
        return new Message();
    }

因此你可從 sample code 知道

Handler 呼叫 obtainMessage 的時候,其實是由 mPool 取出 Message來
將 msg.target 設為原 Handler. 並且設定好 what, arg1, arg2 等參數
好讓 Looper 來執行它 …
———————————————–

(4) 接續 (3) 中的 example code, 它的 sendMessage() 又作了什麼事呢 ?
class AnyClass implements Runnable {
 public void run() {
         Looper.prepare();
         h = new Handler(){
               public void handleMessage(Message msg) {
                  EventHandler ha = new EventHandler(Looper.getMainLooper());
                    String obj = (String)msg.obj + ”, myThread”;
                     Message m = ha.obtainMessage(1, 1, 1, obj);
                     ha.sendMessage(m); //sendMessage 作什麼事呢?
         }
       };
  Looper.loop();
  }
}

                                                                                
以這個例子,簡單來說,Looper.getMainLooper() 會回傳一個ActivityThread的
Looper object, 即為 Looper.mMainLooper. 而mMainLooper有自己的mQueue
==================================================
在此穿插一小段 sendMessage() 的作用
Handler本身在暫存一個mQueue, 當Handler的成員函數sendMessage 被呼叫時,即是把帶著 Handler ha 的 Message m,enqueue 至 Handler自己存存的mQueue中。而mQueue的設置,通常是在建構子就被決定好的。因此你得特別注意 Handler 的建構子。
==================================================

像上面的例子中 sendMessage 即是把帶著 Handler ha 的 Message m,enqueue 至 mMainLooper.mQueue
sendMessage 即是把帶著 Handler ha 的 Message m,enqueue 至 mMainLooper.mQueue

好讓 mMainLooper.loop() 函數把 m 由這個 mMainLooper.mQueue取出(取出時名為msg)
來dispatchMessage,因此就會執行到 msg.target.handleMessage(0
也就是 exmaple code 中的 ha.handleMessage();

因為在 Handler ha = new Handler(Looper looper) 這 Ctor 時,
ha.mLooper = looper 便被紀錄下來,而且ha.mQueue=looper.mQueue也被紀錄下來
也就是 looper.mQueue    (PS:若是用 new Handler(), 則looper取Looper.myLooper())

當 ha.sendMessage 被執行時,便將 msg 塞入 looper.mQueue
—————————————————————–

 

(5) 所以整個 Looper, Message, MessageQueue, Handler 的運作原理是什麼?

因此你的 ha = JohnHandler(MaryLooper) 就像信紙一樣,上面寫著Dear MaryLooper:
上面寫著要執行的程式碼 handleMessage(msg)
透過信封(Message),以Handler.java 的 sendMessage 將信紙(Handler)傳出去
傳到 MaryLooper 的個人信箱 MessageQueue (也就是MaryLooper.mQueue)

在 MaryLooper 中,有個有個固定的 loop() 會不斷被執行
(假設當初宣告此looper的thread, 有 去running 此 function loop 的話 )

那麼 loop 會收到 Message msg. 而 msg.target (Handler) 即為 JohnHandler這封信紙
看著 JohnHandler 上有 handleMessage() 的信紙內容,
故對 Handler 執行了 dipsatchMessage(),因此執行了 JohnHandler
當初信紙內容的交辦事項。

 

 

分享到:
评论

相关推荐

    android_os_MessageQueue.rar_android

    在Android操作系统中,MessageQueue是实现线程间通信和异步处理的核心组件。...通过分析`android_os_MessageQueue.cpp`源代码,开发者可以更深入地了解这个过程,从而优化性能或解决与消息处理相关的复杂问题。

    Android应用程序消息处理机制(Looper、Handler)分析

    Looper是消息循环的载体,它在一个线程中运行,不断地检查消息队列(MessageQueue)是否有待处理的消息。当有新消息到达时,Looper会取出消息并交给对应的Handler进行处理。在Android中,每个线程都有一个Looper,但...

    android handle线程数据传递 源代码

    在给定的文件"Android-Handler-1"中,可能包含了关于创建和使用Handler的详细源代码示例。"Android-Activity-Service-2"和"Android-Activity-Service-1"可能涉及到服务(Service)与Activity之间的通信,这同样可能...

    android Looper

    结合博客文章中的“源码”标签,我们可以推测作者可能深入解析了`Looper`、`Handler`和`Message`的内部实现,包括它们如何协作,以及在Java或Android的源代码层面是如何组织和运行的。这可能会涉及线程同步、内存...

    安卓Android源码——HandlerMessage1.rar

    `HandlerMessage1.rar` 文件可能包含的就是关于这些组件的详细源代码分析和示例。 `Handler` 是一个用于发送和处理消息的对象,它通常在主线程(UI线程)中创建。开发者可以通过 `Handler` 发送 `Message` 到消息...

    〔原创〕Android消息传递机制(总结)

    首先,Android的消息传递机制主要由Handler、Message、Looper和MessageQueue四个关键组件构成。它们共同协作,使得线程间的数据交互变得可能。 1. **Handler**:Handler是消息处理的中心角色,它负责发送和处理...

    android.jar源码 安卓9.0

    6. **多线程与异步处理**:`Handler`、`Looper`和`MessageQueue`是Android中的消息处理机制,源码解读可帮助理解线程同步和异步操作。 7. **系统服务**:`SystemServiceRegistry`管理着Android系统服务,如`...

    android.jar 源码

    6. **线程与异步任务**:Android对线程管理有特殊要求,源码中可以看到Handler、Looper和MessageQueue如何协同工作,以及AsyncTask的内部实现。 7. **权限管理**:Android的权限模型是其安全特性的一部分,源码展示...

    Android优化大师源代码.rar

    2.1 并发与多线程:源码中可能利用了Java的并发库,如ExecutorService,以及Android的Handler、Looper和MessageQueue机制,实现高效的任务调度。 2.2 异步处理:对于耗时操作,如网络请求和数据库操作,源码可能会...

    Android开发案例驱动教程 配套代码

    8.4.2 Message和MessageQueue 169 8.4.3 Handler 169 8.4.4 Looper和HandlerThread 172 本章小结 178 第9章 Activity和Intent 179 9.1 Activity 179 9.1.1 创建Activity 179 9.1.2 Activity生命周期 180 9.2...

    Android应用源码之18.消息处理详解.zip

    消息处理详解.zip”提供了一套深入理解Android消息处理机制的源代码示例,适合开发者参考和学习。以下是关于Android消息处理的一些关键知识点: 1. **Handler(处理器)**:Handler是Android中处理消息的核心组件,...

    android面试题.txt

    Looper、Handler与MessageQueue的关系 - **解释:** 这三个组件共同实现了Android的消息循环机制。 - **具体关系:** - `Looper`负责循环处理消息队列中的消息。 - `Handler`负责发送消息到消息队列,并且可以...

    史上最全的android面试题库.pdf

    - **优点**: 开放源代码、生态系统丰富、跨平台兼容性好、强大的开发工具支持等。 - **缺点**: 版本碎片化严重、安全性问题较多、硬件适配复杂等。 以上知识点涵盖了Android开发中的一些核心概念和技术细节,对于...

    Android应用源码LumaQQ- qq 代码.zip

    在Android中,`Handler`、`Looper`、`MessageQueue`协同工作,实现线程间通信。LumaQQ源码可能运用了这些机制来在主线程和工作线程之间传递信息,处理耗时任务,确保用户界面的流畅性。 七、权限管理 随着Android...

    activity message loop

    标签“源码”表明,该资源可能深入解析了Android系统的源代码,让开发者有机会看到Looper和Handler类的具体实现,这对于进行性能优化或者定制化开发很有帮助。而“工具”可能意味着博客中提到了一些辅助分析或调试...

    Android中的消息处理实例之一

    本文介绍了Android中的消息处理机制,给出了Android消息处理中的几个重点类Handler、Message、MessageQueue、Looper、Runnable、Thread的详细介绍,提供了两个消息处理的实例代码,并深入Android源代码分析了使用...

    安卓UI线程机制 ,在子线程中访问UI

    3. Handler:Handler是Android中进行线程间通信的关键组件,它与Looper和MessageQueue紧密关联。Handler可以发送Message到MessageQueue,同时也可以处理由Looper传递过来的消息。这样,即使任务在子线程中创建,也...

    Android中的消息处理实例之二

    本文介绍了Android中的消息处理机制,给出了Android消息处理中的几个重点类Handler、Message、MessageQueue、Looper、Runnable、Thread的详细介绍,提供了两个消息处理的实例代码,并深入Android源代码分析了使用...

    Android通用多个线程通信管理框架.doc

    `Looper`是消息循环器,它会不断检查`MessageQueue`是否有待处理的消息,如果有,则调用Handler的`handleMessage`方法。 - 因为主线程默认已经有一个运行的Looper,所以在主线程中创建的Handler可以正常接收消息。...

    Android API手册 语法大全

    16. **Handler、Looper和MessageQueue**:用于在主线程和其他线程之间同步通信。 17. **Parcelable和Serializable**:数据序列化接口,用于对象的持久化和跨进程传输。 18. **Loader**:用于异步加载数据,特别...

Global site tag (gtag.js) - Google Analytics