关于Android中的Handler,Message,Looper,MessageQueue和Thread的之间的通信机制

在Android中的职责

Message:消息,其中包含了消息ID,消息处理对象以及需要处理的任意类型的数据等,由MessageQueue统一列队,终由Handler处理。

Handler:既是消息的发送者也是消息的处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。

MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO的原则。然而存放并非实际意义上的存放,而是将Message以链表的方式串联起来的,等待Looper的抽取。

Looper:消息循环,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper,创建Looper的时候会创建一个MessageQueue。

Thread:线程,负责调度整个消息循环。

接下来看一下消息的循环过程:

1)首先要有Message

   message的创建要么从消息池中取,要么创建一个新的消息对象

       Message msg = Message.obtain();

       msg.what = what;
       msg.obj=obj;

   

2)发送消息到消息队列

  msg.obtain(handler,what,obj).sendToTarget();

   sendToTarget()目的是为了在处理消息环节,Message能找到正确的Handler,再将这个Message纳入到消息队列中。

3)利用Looper来抽取MessageQueue中的Message

     

关于Android中的Handler,Message,Looper,MessageQueue和Thread的之间的通信机制
 1 Looper me = myLooper();
 2         MessageQueue queue = me.mQueue;
 3         while (true) {
 4             Message msg = queue.next(); // might block
 5             if (msg != null) {
 6                 if (msg.target == null) {
 7                     // No target is a magic identifier for the quit message.
 8                     return;
 9                 }
10                 msg.target.dispatchMessage(msg);
11                 msg.recycle();
12             }
13         }
关于Android中的Handler,Message,Looper,MessageQueue和Thread的之间的通信机制

 

在Looper的loop()函数里,我们看到,这里有一个死循环,不断地从MessageQueue中获取下一个(next方法)Message,然后通过Message中携带的target信息,交由正确的Handler处理(dispatchMessage方法)。

 

4)handler处理Message

    

关于Android中的Handler,Message,Looper,MessageQueue和Thread的之间的通信机制
 1  if (msg.callback != null) {
 2             handleCallback(msg);
 3         } else {
 4             if (mCallback != null) {
 5                 if (mCallback.handleMessage(msg)) {
 6                     return;
 7                 }
 8             }
 9             handleMessage(msg);
10         }
关于Android中的Handler,Message,Looper,MessageQueue和Thread的之间的通信机制

 

在Handle的dispatchMessage(Message msg)方法里,其中的一个分支就是调用handleMessage方法来处理这条Message,而这也正是我们在职责处描述使用Handler时需要实现handleMessage(Message msg)的原因。

至于dispatchMessage方法中的另外一个分支,我将会在后面的内容中说明。

至此,我们看到,一个Message经由Handler的发送,MessageQueue的入队,Looper的抽取,最终交由Handler处理。而绕的这一圈,也正好帮助我们将同步操作变成了异步操作。

 

Handler所处的线程及更新UI的方式。

在主线程(UI线程)里,如果创建Handler时不传入Looper对象,那么将直接使用主线程(UI线程)的Looper对象(系统已经帮我们创建了);在其它线程里,如果创建Handler时不传入Looper对象,那么,这个Handler将不能接收处理消息。在这种情况下,通用的作法是:

            

关于Android中的Handler,Message,Looper,MessageQueue和Thread的之间的通信机制
 1 class LooperThread extends Thread {
 2         public Handler mHandler;
 3           public void run() {
 4               Looper.prepare();
 5               mHandler = new Handler() {
 6               public void handleMessage(Message msg) {
 7                 // process incoming messages here
 8               }
 9              };
10                Looper.loop();
11          }
12   }
关于Android中的Handler,Message,Looper,MessageQueue和Thread的之间的通信机制

 

在创建Handler之前,为该线程准备好一个Looper(Looper.prepare),然后让这个Looper跑起来(Looper.loop),抽取Message,这样,Handler才能正常工作。

因此,Handler处理消息总是在创建Handler的线程里运行。而我们的消息处理中,不乏更新UI的操作,不正确的线程直接更新UI将引发异常。因此,需要时刻关心Handler在哪个线程里创建的。

如何更新UI才能不出异常呢?SDK告诉我们,有以下4种方式可以从其它线程访问UI线程:

·      Activity.runOnUiThread(Runnable)

·      View.post(Runnable)

·      View.postDelayed(Runnable, long)

·      Handler

其中,重点说一下的是View.post(Runnable)方法。在post(Runnable action)方法里,View获得当前线程(即UI线程)的Handler,然后将action对象post到Handler里。在Handler里,它将传递过来的action对象包装成一个Message(Message的callback为action),然后将其投入UI线程的消息循环中。在Handler再次处理该Message时,有一条分支(未解释的那条)就是为它所设,直接调用runnable的run方法。而此时,已经路由到UI线程里,因此,我们可以毫无顾虑的来更新UI。(也可以说回调,handler将Runnable对象发送到MessageQueue然后回调run方法执行UI更新操作)

 

再讲一下消息处理的派发机制

dispatchMessage

 

关于Android中的Handler,Message,Looper,MessageQueue和Thread的之间的通信机制
 1 public void dispatchMessage(Message msg) {
 2 
 3         if (msg.callback !=null) {
 4 
 5             handleCallback(msg);
 6 
 7         } else {
 8 
 9           if (mCallback !=null) {
10 
11                 if (mCallback.handleMessage(msg)) {
12 
13                     return;
14 
15                 }
16 
17            }
18 
19             handleMessage(msg);
20 
21         }
22 
23 }
关于Android中的Handler,Message,Looper,MessageQueue和Thread的之间的通信机制

 

2  --  如果msg.callback不为空,则调用handleCallback(msg);

callback是一个Runnable的实例,那么什么时候不为空呢?

|-  当调用 message 的obtain静态方法来实例化Message的时候,会对这个Runnable赋值

    public static Message obtain(Handler h, Runnable callback) {

        Message m = obtain();

        m.target = h;

        m.callback = callback;

        return m;

    }

|-  更常用的方式

    当Handler.post(Runnable r)的时候

关于Android中的Handler,Message,Looper,MessageQueue和Thread的之间的通信机制
 1  public final boolean post(Runnable r)
 2 
 3      return  sendMessageDelayed(getPostMessage(r), 0);
 4 
 5 }
 6 
 7     private final Message getPostMessage(Runnable r) {
 8 
 9         Message m = Message.obtain();
10 
11         m.callback = r;
12 
13         return m;
14 
15 }
关于Android中的Handler,Message,Looper,MessageQueue和Thread的之间的通信机制

 


   

 

这时候,handler  dispatch这个消息会直接调用Runnable中的run方法

这也是为什么重写的handlerMessage不对这种形式发送的消息进行处理

 

2  如果mCallback不为空,则调用mCallback.handleMessage方法

而这个Callback默认情况下为空,只有当调用

public Handler(Callback callback)或者public Handler(Looper looper, Callback callback)这两种构造方法的时候才会被赋值,其实也就是要直接通过new hanlder ()构造实例使用,而不是通过内部类重写handlerMessage 方式来处理的时侯采用的手段。


    当然,一般使用handler处理消息都是为了与ui线程通信,而ui的looper是系统维护的,所以推荐第一种方式。 

    当dispatch消息的时候,会直接调用callback.handleMessage()方法

 

2  前边两个都为空的时候,才会调用Handler的handleMessage方法,如果没有重写,则调用系统默认的handleMessage,即什么也不做

总结:

·      Handler的处理过程运行在创建Handler的线程里

·      一个Looper对应一个MessageQueue

·      一个线程对应一个Looper

·      一个Looper可以对应多个Handler

·      不确定当前线程时,更新UI时尽量调用post方法

 

关于Android中的Handler,Message,Looper,MessageQueue和Thread的之间的通信机制,布布扣,bubuko.com

关于Android中的Handler,Message,Looper,MessageQueue和Thread的之间的通信机制

上一篇:Android记事本开发之界面设计


下一篇:nagios系列-----Redhat5.4下安装EPEL