Android 中Message,MessageQueue,Looper,Handler詳解+例項

lostinai發表於2013-05-06

http://www.open-open.com/lib/view/open1331276072249.html

一、幾個關鍵概念


1、MessageQueue:是一種資料結構,見名知義,就是一個訊息佇列,存放訊息的地方。每一個執行緒最多隻可以擁有一個MessageQueue資料結構。
建立一個執行緒的時候,並不會自動建立其MessageQueue。通常使用一個Looper物件對該執行緒的MessageQueue進行管理。主執行緒建立時,會建立一
個預設的Looper物件,而Looper物件的建立,將自動建立一個Message Queue。其他非主執行緒,不會自動建立Looper,要需要的時候,通過調
用prepare函式來實現。

2、Message:訊息物件,Message Queue中的存放的物件。一個Message Queue中包含多個Message。
Message例項物件的取得,通常使用Message類裡的靜態方法obtain(),該方法有多個過載版本可供選擇;它的建立並不一定是直接建立一個新的例項,
而是先從Message Pool(訊息池)中看有沒有可用的Message例項,存在則直接取出返回這個例項。如果Message Pool中沒有可用的Message例項,
則才用給定的引數建立一個Message物件。呼叫removeMessages()時,將Message從Message Queue中刪除,同時放入到Message Pool中。除了上面這
種方式,也可以通過Handler物件的obtainMessage()獲取一個Message例項。

3、Looper:
是MessageQueue的管理者。每一個MessageQueue都不能脫離Looper而存在,Looper物件的建立是通過prepare函式來實現的。同時每一個Looper物件
和一個執行緒關聯。通過呼叫Looper.myLooper()可以獲得當前執行緒的Looper物件
建立一個Looper物件時,會同時建立一個MessageQueue物件。除了主執行緒有預設的Looper,其他執行緒預設是沒有MessageQueue物件的,所以,不能
接受Message。如需要接受,自己定義一個Looper物件(通過prepare函式),這樣該執行緒就有了自己的Looper物件和MessageQueue資料結構了。
Looper從MessageQueue中取出Message然後,交由Handler的handleMessage進行處理。處理完成後,呼叫Message.recycle()將其放入Message Pool中。

4、Handler:
訊息的處理者,handler負責將需要傳遞的資訊封裝成Message,通過呼叫handler物件的obtainMessage()來實現;
將訊息傳遞給Looper,這是通過handler物件的sendMessage()來實現的。繼而由Looper將Message放入MessageQueue中。
當Looper物件看到MessageQueue中含有Message,就將其廣播出去。該handler物件收到該訊息後,呼叫相應的handler物件的handleMessage()方法
對其進行處理。
二、執行緒之間的訊息如何進行傳遞

1、主執行緒給自己傳送Message

01 <b>package test.message;
02  
03 import android.app.Activity;
04 import android.os.Bundle;
05 import android.os.Handler;
06 import android.os.Looper;
07 import android.os.Message;
08 import android.view.View;
09 import android.widget.Button;
10 import android.widget.TextView;
11  
12 public class MainActivity extends Activity {
13      
14     private Button btnTest;
15     private TextView textView;
16      
17     private Handler handler;
18      
19     @Override
20     public void onCreate(Bundle savedInstanceState) {
21         super.onCreate(savedInstanceState);
22         setContentView(R.layout.main);
23          
24         btnTest = (Button)this.findViewById(R.id.btn_01);
25         textView = (TextView)this.findViewById(R.id.view_01);
26          
27         btnTest.setOnClickListener(new View.OnClickListener() {
28              
29             @Override
30             public void onClick(View arg0) {
31                  
32                 Looper looper = Looper.getMainLooper(); //主執行緒的Looper物件
33                 //這裡以主執行緒的Looper物件建立了handler,
34                 //所以,這個handler傳送的Message會被傳遞給主執行緒的MessageQueue。
35                 handler = new MyHandler(looper);
36                 handler.removeMessages(0);
37                 //構建Message物件
38                 //第一個引數:是自己指定的message代號,方便在handler選擇性地接收
39                 //第二三個引數沒有什麼意義
40                 //第四個引數需要封裝的物件
41                 Message msg = handler.obtainMessage(1,1,1,"主執行緒發訊息了");
42                  
43                 handler.sendMessage(msg); //傳送訊息
44                  
45             }
46         });
47     }
48      
49     class MyHandler extends Handler{
50          
51         public MyHandler(Looper looper){
52             super(looper);
53         }
54          
55         public void handleMessage(Message msg){
56             super.handleMessage(msg);
57             textView.setText("我是主執行緒的Handler,收到了訊息:"+(String)msg.obj);
58         }
59     }
60 }</b>

2、其他執行緒給主執行緒傳送Message

01 <b>package test.message;
02  
03 import android.app.Activity;
04 import android.os.Bundle;
05 import android.os.Handler;
06 import android.os.Looper;
07 import android.os.Message;
08 import android.view.View;
09 import android.widget.Button;
10 import android.widget.TextView;
11  
12 public class MainActivity extends Activity {
13      
14     private Button btnTest;
15     private TextView textView;
16      
17     private Handler handler;
18      
19     @Override
20     public void onCreate(Bundle savedInstanceState) {
21         super.onCreate(savedInstanceState);
22         setContentView(R.layout.main);
23          
24         btnTest = (Button)this.findViewById(R.id.btn_01);
25         textView = (TextView)this.findViewById(R.id.view_01);
26          
27         btnTest.setOnClickListener(new View.OnClickListener() {
28              
29             @Override
30             public void onClick(View arg0) {
31                  
32                 //可以看出這裡啟動了一個執行緒來操作訊息的封裝和傳送的工作
33                 //這樣原來主執行緒的傳送就變成了其他執行緒的傳送,簡單吧?呵呵
34                 new MyThread().start();   
35             }
36         });
37     }
38      
39     class MyHandler extends Handler{
40          
41         public MyHandler(Looper looper){
42             super(looper);
43         }
44          
45         public void handleMessage(Message msg){
46             super.handleMessage(msg);
47             textView.setText("我是主執行緒的Handler,收到了訊息:"+(String)msg.obj);
48         }
49     }
50      
51     //加了一個執行緒類
52     class MyThread extends Thread{
53          
54         public void run(){
55             Looper looper = Looper.getMainLooper(); //主執行緒的Looper物件
56             //這裡以主執行緒的Looper物件建立了handler,
57             //所以,這個handler傳送的Message會被傳遞給主執行緒的MessageQueue。
58             handler = new MyHandler(looper);
59  
60             //構建Message物件
61             //第一個引數:是自己指定的message代號,方便在handler選擇性地接收
62             //第二三個引數沒有什麼意義
63             //第四個引數需要封裝的物件
64             Message msg = handler.obtainMessage(1,1,1,"其他執行緒發訊息了");
65              
66             handler.sendMessage(msg); //傳送訊息           
67         }
68     }
69 }<span style="font-family:Arial;"><span style="white-space:normal;"> </span></span></b>

3、主執行緒給其他執行緒傳送Message

01 <b>package test.message;
02  
03 import android.app.Activity;
04 import android.os.Bundle;
05 import android.os.Handler;
06 import android.os.Looper;
07 import android.os.Message;
08 import android.view.View;
09 import android.widget.Button;
10 import android.widget.TextView;
11  
12 public class MainActivity extends Activity {
13      
14     private Button btnTest;
15     private TextView textView;
16      
17     private Handler handler;
18      
19     @Override
20     public void onCreate(Bundle savedInstanceState) {
21         super.onCreate(savedInstanceState);
22         setContentView(R.layout.main);
23          
24         btnTest = (Button)this.findViewById(R.id.btn_01);
25         textView = (TextView)this.findViewById(R.id.view_01);
26          
27          
28         //啟動執行緒
29         new MyThread().start();   
30          
31         btnTest.setOnClickListener(new View.OnClickListener() {
32              
33             @Override
34             public void onClick(View arg0) {
35                 //這裡handler的例項化線上程中
36                 //執行緒啟動的時候就已經例項化了
37                 Message msg = handler.obtainMessage(1,1,1,"主執行緒傳送的訊息");
38                 handler.sendMessage(msg);
39             }
40         });
41     }
42      
43     class MyHandler extends Handler{
44          
45         public MyHandler(Looper looper){
46             super(looper);
47         }
48          
49         public void handleMessage(Message msg){
50             super.handleMessage(msg);
51             textView.setText("我是主執行緒的Handler,收到了訊息:"+(String)msg.obj);
52         }
53     }
54      
55     class MyThread extends Thread{
56          
57         public void run(){
58             Looper.prepare(); //建立該執行緒的Looper物件,用於接收訊息
59              
60             //注意了:這裡的handler是定義在主執行緒中的哦,呵呵,
61             //前面看到直接使用了handler物件,是不是在找,在什麼地方例項化的呢?
62             //現在看到了吧???呵呵,開始的時候例項化不了,因為該執行緒的Looper物件
63             //還不存在呢。現在可以例項化了
64             //這裡Looper.myLooper()獲得的就是該執行緒的Looper物件了
65             handler = new ThreadHandler(Looper.myLooper());
66              
67             //這個方法,有疑惑嗎?
68             //其實就是一個迴圈,迴圈從MessageQueue中取訊息。
69             //不經常去看看,你怎麼知道你有新訊息呢???
70             Looper.loop();
71  
72         }
73          
74         //定義執行緒類中的訊息處理類
75         class ThreadHandler extends Handler{
76              
77             public ThreadHandler(Looper looper){
78                 super(looper);
79             }
80              
81             public void handleMessage(Message msg){
82                 //這裡對該執行緒中的MessageQueue中的Message進行處理
83                 //這裡我們再返回給主執行緒一個訊息
84                 handler = new MyHandler(Looper.getMainLooper());
85                  
86                 Message msg2 = handler.obtainMessage(1,1,1,"子執行緒收到:"+(String)msg.obj);
87                  
88                 handler.sendMessage(msg2);
89             }
90         }
91     }
92 }</b>

4、其他執行緒給自己傳送Message 

01 <b>package test.message;
02  
03 import android.app.Activity;
04 import android.os.Bundle;
05 import android.os.Handler;
06 import android.os.Looper;
07 import android.os.Message;
08 import android.view.View;
09 import android.widget.Button;
10 import android.widget.TextView;
11  
12 public class MainActivity extends Activity {
13      
14     private Button btnTest;
15     private TextView textView;
16      
17     private Handler handler;
18      
19     @Override
20     public void onCreate(Bundle savedInstanceState) {
21         super.onCreate(savedInstanceState);
22         setContentView(R.layout.main);
23          
24         btnTest = (Button)this.findViewById(R.id.btn_01);
25         textView = (TextView)this.findViewById(R.id.view_01);
26          
27          
28         btnTest.setOnClickListener(new View.OnClickListener() {
29              
30             @Override
31             public void onClick(View arg0) {
32                 //啟動執行緒
33                 new MyThread().start();   
34             }
35         });
36     }
37      
38     class MyHandler extends Handler{
39          
40         public MyHandler(Looper looper){
41             super(looper);
42         }
43          
44         public void handleMessage(Message msg){
45             super.handleMessage(msg);
46             textView.setText((String)msg.obj);
47         }
48     }   
49      
50     class MyThread extends Thread{
51          
52         public void run(){
53             Looper.prepare(); //建立該執行緒的Looper物件
54             //這裡Looper.myLooper()獲得的就是該執行緒的Looper物件了
55             handler = new ThreadHandler(Looper.myLooper());
56             Message msg = handler.obtainMessage(1,1,1,"我自己");
57             handler.sendMessage(msg);
58              
59             Looper.loop();
60  
61         }
62          
63         //定義執行緒類中的訊息處理類
64         class ThreadHandler extends Handler{
65              
66             public ThreadHandler(Looper looper){
67                 super(looper);
68             }
69              
70             public void handleMessage(Message msg){
71                 //這裡對該執行緒中的MessageQueue中的Message進行處理
72                 //這裡我們再返回給主執行緒一個訊息
73                 //加入判斷看看是不是該執行緒自己發的資訊
74                 if(msg.what == 1 && msg.obj.equals("我自己")){
75                      
76                     handler = new MyHandler(Looper.getMainLooper());
77                      
78                     Message msg2 = handler.obtainMessage(1,1,1,"稟告主執行緒:我收到了自己發給自己的Message");
79                      
80                     handler.sendMessage(msg2);               
81                 }
82  
83             }
84         }
85     }
86 }</b>
原文轉自 :http://tanghaibo001.blog.163.com/blog/static/9068612020111287218197/

相關文章