Android 事件处理模型(三)消息传递机制: Handler Looper MessageQueue

来源:互联网 发布:网络蜘蛛并行策略 编辑:程序博客网 时间:2024/05/16 05:17

最近的工作涉及了Android的Handler消息传递,总结如下:

1. Handler :

为了实现线程和Activity中widget之间的通信,比如为了进行某些耗时操作而新开的线程,在这些操作中如果要跟新UI则需要Handler来处理。它主要负责Message的分发和实现不同Message操作的自定义,相当于句柄。

2. MessageQuene:

Message是线程和widget通信的介质,也就是来传递信息的,显然MessageQuene则是保存Message的列表,在代码中表现为ArrayList。

3. Looper:

是一个控制器,它不断的从MessageQuene中取Message,然后将Message传递给Handler中的handleMessage方法以实现用户自定义操作。


一个线程只能有一个Looper,线程中可能有多个Handler,一个Looper管理一个MessageQuene,不同线程的Looper由ThreadLocal管理。


整个工作流程如下:

1. 线程工作流程

线程注册Looper =>

线程注册Handler=>

Handler sendMessage 到 MessageQuene 


 2. Looper工作流程

在Looper.prepare()中Looper被注册 =>

Looper执行Looper.loop() 取MessageQuene中的Message,执行Message的Handler(句柄)的handlerMessage方法,实现自定义操作。 =>

Looper的管理通过ThreadLocal类实现,ThreadLocal机制:为不同线程管理变量副本,实现多线程异步操作。


源码分析如下:

 1. 调用流程

[java] view plaincopy
  1. public class HelloAndroidActivity extends Activity {  
  2.     Handler handler = new Handler() {//根据返回Message自定义操作  
  3.         public void handleMessage(Message msg) {  
  4.         ......  
  5.         }  
  6.     }  
  7.     @Override  
  8.     public void onCreate(Bundle savedInstanceState) {  
  9.         super.onCreate(savedInstanceState);  
  10.         setContentView(R.layout.main);  
  11.         Thread thread = new Thread() {  
  12.             public void run() {  
  13.                 Looper.prepare();//注册Looper  
  14.                 ........  
  15.                 Looper.loop();//Looper开始操作MessageQuene  
  16.                 handler.sendMessage(new Message());//发送消息到MessageQuene  
  17.             }  
  18.         };  
  19.         thread.start();//启动线程  
  20.     }  
  21. }  

2. Handler 分析

[java] view plaincopy
  1. /** 
  2.  * A Handler allows you to send and process {@link Message} and Runnable 
  3.  * objects associated with a thread's {@link MessageQueue}.  Each Handler 
  4.  * instance is associated with a single thread and that thread's message 
  5.  * queue.  When you create a new Handler, it is bound to the thread / 
  6.  * message queue of the thread that is creating it -- from that point on, 
  7.  * it will deliver messages and runnables to that message queue and execute 
  8.  * them as they come out of the message queue. 
  9.  */  
  10. public class Handler {  
  11.     /** 
  12.      * Subclasses must implement this to receive messages. 
  13.      */  
  14.     public void handleMessage(Message msg) {  
  15.     }  
[java] view plaincopy
  1.     /** 初始化handler,确认Handler的mLooper, mQueue,callback等等<pre name="code" class="java">     * Use the {@link Looper} for the current thread with the specified callback interface</pre>     * and set whether the handler should be asynchronous.<br> 
  2.      *<br> 
  3.      * Handlers are synchronous by default unless this constructor is used to make<br> 
  4.      * one that is strictly asynchronous.<br> 
  5.      *<br> 
  6.      * Asynchronous messages represent interrupts or events that do not require global ordering<br> 
  7.      * with represent to synchronous messages.  Asynchronous messages are not subject to<br> 
  8.      * the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.<br> 
  9.      *<br> 
  10.      * @param callback The callback interface in which to handle messages, or null.<br> 
  11.      * @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for<br> 
  12.      * each {@link Message} that is sent to it or {@link Runnable} that is posted to it.<br> 
  13.      *<br> 
  14.      * @hide<br> 
  15.      */<br>  
  16.     public Handler(Callback callback, boolean async) {<br>  
  17.         if (FIND_POTENTIAL_LEAKS) {<br>  
  18.             final Class<? extends Handler> klass = getClass();<br>  
  19.             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&<br>  
  20.                     (klass.getModifiers() & Modifier.STATIC) == 0) {<br>  
  21.                 Log.w(TAG, "The following Handler class should be static or leaks might occur: " +<br>  
  22.                     klass.getCanonicalName());<br>  
  23.             }<br>  
  24.         }<br>  
  25. <br>  
  26. <br>  
  27.         mLooper = Looper.myLooper();<br>  
  28.         if (mLooper == null) {<br>  
  29.             throw new RuntimeException(<br>  
  30.                 "Can't create handler inside thread that has not called Looper.prepare()");<br>  
  31.         }<br>  
  32.         mQueue = mLooper.mQueue;<br>  
  33.         mCallback = callback;<br>  
  34.         mAsynchronous = async;<br>  
  35.     } /** * Handle system messages here. */在Looper.loop()中会调用这个函数,实现handle message public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } }  
  36.  handleMessage(msg); } } /** * Default constructor associates this handler with the queue for the * current thread. * * If there isn't one, this handler won't be able to receive messages. */ public Handler() { mLooper = Looper.myLooper();//获取该线程Looper if (mLooper  
  37.  == null) {//确保该线程已注册Looper throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = null; } /** * Returns a new {@link android.os.Message Message} from the global message  
  38.  pool. More efficient than * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this). * If you don't want that facility, just call Message.obtain() instead. */获取消息,比new效率高 public final Message  
  39.  obtainMessage() { return Message.obtain(this); } /** * Causes the Runnable r to be added to the message queue. * The runnable will be run on the thread to which this handler is * attached. * * @param r The Runnable that will be executed. * * @return Returns 
  40.  true if the Runnable was successfully placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */ public final boolean post(Runnable r) { return sendMessageDelayed(getPostMessage(r),  
  41.  0); } /** * Pushes a message onto the end of the message queue after all pending messages * before the current time. It will be received in {@link #handleMessage}, * in the thread attached to this handler. * * @return Returns true if the message was successfully 
  42.  placed in to the * message queue. Returns false on failure, usually because the * looper processing the message queue is exiting. */网MessageQuene中加入消息 public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); } /** * Remove any pending 
  43.  posts of messages with code 'what' that are in the * message queue. */ public final void removeMessages(int what) { mQueue.removeMessages(this, what, nulltrue); }}  
  44. <pre></pre>  
  45. <strong>3. Looper分析</strong>  
  46. <p></p>  
  47. <p></p>  
  48. <pre name="code" class="java">/** 
  49.  * Class used to run a message loop for a thread.  Threads by default do 
  50.  * not have a message loop associated with them; to create one, call 
  51.  * {@link #prepare} in the thread that is to run the loop, and then 
  52.  * {@link #loop} to have it process messages until the loop is stopped. 
  53.  */  
  54. public class Looper {  
  55.     Thread mThread;  
  56.     private static Looper mMainLooper = null;  
  57.   
  58.     /** Initialize the current thread as a looper. 
  59.      * This gives you a chance to create handlers that then reference 
  60.      * this looper, before actually starting the loop. Be sure to call 
  61.      * {@link #loop()} after calling this method, and end it by calling 
  62.      * {@link #quit()}. 
  63.      * 为进程注册Looper,并确保每个进程一个Looper, 
  64.      * ThreadLocal为不同进程分别管理相应Looper 
  65.      */  
  66.     public static final void prepare() {  
  67.        if (sThreadLocal.get() != null) {  
  68.            throw new RuntimeException("Only one Looper may be created per thread");  
  69.        }  
  70.        sThreadLocal.set(new Looper());  
  71.     }  
  72.   
  73.     /** 
  74.      *  Run the message queue in this thread. Be sure to call 
  75.      * {@link #quit()} to end the loop. 
  76.      * 不停的取message,并调用其Handler. 
  77.      */  
  78.     public static final void loop() {  
  79.         Looper me = myLooper();  
  80.         MessageQueue queue = me.mQueue;  
  81.   
  82.         // Make sure the identity of this thread is that of the local process,  
  83.         // and keep track of what that identity token actually is.  
  84.         Binder.clearCallingIdentity();  
  85.         final long ident = Binder.clearCallingIdentity();  
  86.   
  87.         while (true) {  
  88.             Message msg = queue.next(); // might block  
  89.             //if (!me.mRun) {  
  90.             //    break;  
  91.             //}  
  92.             if (msg != null) {  
  93.                 if (msg.target == null) {  
  94.                     // No target is a magic identifier for the quit message.  
  95.                     return;  
  96.                 }  
  97.                 if (me.mLogging!= null) me.mLogging.println(  
  98.                         ">>>>> Dispatching to " + msg.target + " "  
  99.                         + msg.callback + ": " + msg.what  
  100.                         );  
  101.                 msg.target.dispatchMessage(msg);  
  102.                 if (me.mLogging!= null) me.mLogging.println(  
  103.                         "<<<<< Finished to    " + msg.target + " "  
  104.                         + msg.callback);  
  105.   
  106.                 // Make sure that during the course of dispatching the  
  107.                 // identity of the thread wasn't corrupted.  
  108.                 final long newIdent = Binder.clearCallingIdentity();  
  109.   
  110.                 msg.recycle();  
  111.             }  
  112.         }  
  113.     }  
  114.       
  115.     /** 
  116.      * Return the Looper object associated with the current thread.  Returns 
  117.      * null if the calling thread is not associated with a Looper. 
  118.      * 获取当前线程Looper 
  119.      */  
  120.     public static final Looper myLooper() {  
  121.         return (Looper)sThreadLocal.get();  
  122.     }  
  123. }</pre><br>  
  124. <br>  
  125. <p></p>  
  126. <blockquote style="margin:0 0 0 40px; border:none; padding:0px">  
  127. <p><br>  
  128. </p>  
  129. <p><br>  
  130. </p>  
  131. </blockquote>  
  132. <br>  
  133. <pre></pre>  
原创粉丝点击