Message,MessageQueue,Handler,Looper,Thread,ThreadLocal

Message:单个消息体,承载了两个线程之间交流的信息。不同的消息由"what"来区分。

MessageQueue:消息链表,所有从非UI线程发过来的Message都被加入到这个队列中。其实这个类主要功能就是往mMessage的next加入新的消息,然后提供给Looper获取。

Handler:在非主线程中发送消息,并且在主线程中处理消息。(自己发送给自己,好变态。)

Looper: 遍历MessageQueue中所有没有处理过的消息,发送给Handler处理。

Thread:非主线程。上面所有的东西都是为了该线程和主线程交互数据(比如View)做准备的。

总体流程如下:

 1 UI线程{
 2            //申请Handler对象。
 3            Handler mHandler =new Handler(){
 4            
 5               @Override
 6               public void handleMessage(Message msg) {
 7               
 8                
 9               }
10            };
11            //非主线程
12            Thread{
13                run(){
14                                       
15                    0: Handler发送Message
16                    1:Message被塞入MessageQueue
17                    2: Looper 不断的遍历MessageQueue,取出消息。
18                    3:在Looper中回调Handler的 handleMessage(Message msg) 函数。
19                    
20                     
21                     
22                }
23            }
24            //整个过程又回到了UI线程中处理。
25         }

总结上面的流程:Handler并没有真正开启另外一个线程,两个线程中通过一个消息队列,实现了数据在两个线程中的"同步"传递。
当然如果只是为了在不同线程间传递数据,直接使用共享变量就可以了。例如可以将Handler的类设置成一个Object对象即可。事实上Handler本身就是个线程中的共享变量。
真正有意义的地方在于:Looper是一个死循环,不断的遍历MessageQueue里面的Message,传递给UI线程的Handler,然后即时的影响UI线程的View的绘画等。整个过程让人感觉是同步操作。

应用层代码:

 1 //注册一个Handler
 2      private Handler mHandler =new Handler(){
 3  
 4         @Override
 5          public void handleMessage(Message msg) {
 6             //do some stuffs
 7          }
 8          
 9       };
10       //启动一个新的线程:
11        new Thread(new Runnable()
12          {
13               
14               
15               @Override
16               public void run() {
17                 //在当前线程中生成一个新的Looper对象
18                 Looper.prepare();
19                 
20                 //给MessageQueue队列插入一条消息。
21                 mHandler.sendEmptyMessage(0);
22                 
23                 //不断的轮询遍历MessageQueue的消息,并且发送给mHandler
24                 Looper.loop();
25                }
26               
27 
28         })start();

源码:
上面的流程中没有看到Looper,MessageQueue,Handler三者之间是怎么建立起练习的。下面部分做出解释:

 1 Looper.java:
 2     public static void prepare() {
 3          //生成了一个新的Looper对象并且保存在sThreadLocal的map中。注意这个map的键key是当前线程的标示,也就是Thread.currentThread()。
 4          //所以每个线程都有一个独立的Looper对象。
 5          sThreadLocal.set(new Looper());
 6          
 7     }
 8     //在Looper对象的初始化中会创建一个新的MessageQueue
 9     private Looper() {
10         mQueue = new MessageQueue();
11     }
12     //通过这个函数获取当前线程创建的Looper对象,前面说过了一个线程只能有一个Looper对象,所以该Looper对象就是上面创建的那个。
13     public static Looper myLooper() {
14         return sThreadLocal.get();
15     }
16 
17 
18 //Looper跟Handler是怎样建立关系的?
19 
20 Handler.java
21     public Handler() {
22         //得到当前线程的Looper对象
23         mLooper = Looper.myLooper();
24         //得到Looper对象的MessageQueue对象的引用
25         mQueue = mLooper.mQueue;
26     }
27  }
28  

通过上面两个构造函数就将Looper,MessageQueue,Handler建立起了关系。

消息的分发:

 1 Handler.java
 2     public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
 3         Message msg = Message.obtain();
 4         msg.what = what;
 5         return sendMessageDelayed(msg, delayMillis){
 6         
 7             MessageQueue queue = mQueue;
 8             if (queue != null) {
 9                 msg.target = this; //这步很重要:将handler的引用记录在了msg.target中。方便后面Looper处理消息后返还消息给Handler的对象。
10                 sent = queue.enqueueMessage(msg, uptimeMillis);
11                 
12                 return sent;
13             }
14         }
15     }
16  MessageQueue.java
17     //将新插入的消息放到消息队列的最后
18     final boolean enqueueMessage(Message msg, long when) {
19         
20         Message p = mMessages;
21         Message prev = null;
22         while (p != null && p.when <= when) {
23             prev = p;
24             p = p.next;
25        }
26         msg.next = prev.next;
27         prev.next = msg;
28     
29     }
30 Looper.java
31     //一个死循环
32     public static void loop() {
33         //得到当前线程的Looper对象
34         Looper me = myLooper();
35         //得到当前线程的消息队列
36         MessageQueue queue = me.mQueue;
37         while (true) {
38             Message msg = queue.next(); // might block
39             if (msg != null) {
40                 //将消息返还给Handler的对象,调用我们覆盖的函数
41                 msg.target.dispatchMessage(msg);
42                 //释放消息队列的中消息
43                 msg.recycle();
44             
45             }
46         }
47     
48     }


从建立关系,到分发消息,最后返还消息的过程大概就是这样了。

过程中还设计到了java中管理线程的一个内容

Looper.java
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

这个对象用于保存不同线程中的数据备份,不涉及android内容。

posted @ 2013-03-27 15:27  mogul  阅读(247)  评论(0编辑  收藏  举报