眼睛一閉一睜一天就過去了哼,眼睛一閉不睜一輩子就過去了哼。
Android執行緒間通訊機制
當android應用程式執行時,一個主執行緒被建立(也稱作UI執行緒),此執行緒主要負責處理UI相關的事件,由於Android採用UI單執行緒模型,所以只能在主執行緒中對UI元素進行操作,如果在非UI執行緒直接對UI進行了操作,則會報錯,另外,對於運算量較大的操作和IO操作,我們需要新開執行緒來處理這些工作,以免阻塞UI執行緒,子執行緒與主執行緒之間是怎樣進行通訊的呢?此時就要採用訊息迴圈機制(Looper)與Handler進行處理。
一、基本概念
Looper:每一個執行緒都可以產生一個Looper,用來管理執行緒的Message,Looper物件會建立一個MessgaeQueue資料結構來存放message。
Handler:與Looper溝通的物件,可以push訊息或者runnable物件到MessgaeQueue,也可以從MessageQueue得到訊息。
檢視其建構函式:
Default constructor associates this handler with the queue for the current thread.//如不指定Looper引數則預設利用當前執行緒的Looper建立
Use the provided queue instead of the default one.//使用指定的Looper物件建立Handler
執行緒A的Handler物件引用可以傳遞給別的執行緒,讓別的執行緒B或C等能送訊息來給執行緒A。
執行緒A的Message Queue裡的訊息,只有執行緒A所屬的物件可以處理。
注意:Android裡沒有global的MessageQueue,不同程序(或APK之間)不能通過MessageQueue交換訊息。
二、Handler通過Message通訊的基本方式
使用Looper.myLooper可以取得當前執行緒的Looper物件。
使用mHandler = new Handler(Looper.myLooper()); 可產生用來處理當前執行緒的Handler物件。
使用mHandler = new Handler(Looper.getMainLooper()
使用Handler傳遞訊息物件時將訊息封裝到一個Message物件中,Message物件中主要欄位如下:
public int |
當需要傳遞的訊息是整形時arg1 和 arg2 是一種低成本的可選方案,他使用 setData()/getData()訪問或修改欄位。 |
|
public int |
同上 |
|
可傳送的任意object型別. |
||
public int |
Int型別使用者自定義的訊息型別碼 |
Message物件可以通過Message類的建構函式獲得,但Google推薦使用Message.obtain()方法獲得,該方法會從全域性的物件池裡返回一個可複用的Messgae例項,API中解釋如下:
Constructor (but the preferred way to get a Message is to call).
Handler發出訊息時,既可以指定訊息被接受後馬上處理,也可以指定經過一定時間間隔之後被處理,如(Message msg, long delayMillis),具體請參考API。
注意:在Android裡,新誕生一個執行緒,並不會自動建立其Message Loop
可以通過呼叫Looper.prepare()為該執行緒建立一個MessageQueue,再呼叫Looper.loop()進行訊息迴圈。
下面舉例說明:
在main.xml中定義兩個button及一個textview
<Button
android:id="@+id/a"
android:layout_width="80dp"
android:layout_height="60dp"
android:padding="6dp"
android:layout_marginTop="10dp"
android:text="Test looper"
android:hint="Test looper" />
<Button
android:id="@+id/b"
android:layout_width="80dp"
android:layout_height="60dp"
android:padding="6dp"
android:layout_marginTop="10dp"
android:text="Exit" />
<TextView
android:id="@+id/tv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"/>
Activity原始碼如下:
1 public class HandlerTestActivity extends Activity implements Button.OnClickListener{
2
3 public TextView tv;
4
5 private myThread myT;
6
7 Button bt1, bt2;
8
9 /** Called when the activity is first created. */
10
11 @Override
12
13 public void onCreate(Bundle savedInstanceState) {
14
15 super.onCreate(savedInstanceState);
16
17 setContentView(R.layout.main);
18
19 bt1 = (Button)findViewById(R.id.a);
20
21 bt2 = (Button)findViewById(R.id.b);
22
23 tv = (TextView)findViewById(R.id.tv);
24
25 bt1.setId(1);//為兩個button設定ID,此ID用於後面判斷是哪個button被按下 26
27 bt2.setId(2);
28
29 bt1.setOnClickListener(this);//增加監聽器 30
31 bt2.setOnClickListener(this);
32
33 }
34
35
36
37 @Override
38
39 public void onClick(View v) {
40
41 // TODO Auto-generated method stub 42
43 switch(v.getId()){//按鍵事件響應,如果是第一個按鍵將啟動一個新執行緒 44
45 case 1:
46