在程序開發時,對於一些比較耗時的操作,我們通常會為其開辟一個單獨的線程來執行,這樣可以盡可能的減少用戶等待的時間。在Android中,默認情況下,所有的操作都是在主線程中進行的,這個主線程負責管理與UI相關的事件,而在我們自己創建的子線程中,又不能對UI組件進行操作,因此,Android提供了消息處理傳遞機制來解決這一個問題。
1、多線程的常見操作
1、創建線程。
在Android中,提供了兩種創建線程的方法。(一種是通過Thread類的構造方法創建線程對象,並重寫run()方法實現,另一種是通過實現Runnable接口來實現。)
第一種方法:
Thread thread=new Thread(new Runnable(){
@Override
public void run(){
//要執行的操作
}
});
thread.start();
第二種方法:
public class MainActivity extends Activity implement Runnable{
@Override
public void run(){
//要執行的操作
}
}
2、開啟線程
3、線程休眠
4、中斷線程
下面用一個實例來實現上述的這些操作
首先是布局文件:

1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="fill_parent" 4 android:layout_height="fill_parent" > 5 6 <Button 7 android:id="@+id/button1" 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" 10 android:text="@string/start" /> 11 12 <Button 13 android:id="@+id/button2" 14 android:layout_width="wrap_content" 15 android:layout_height="wrap_content" 16 android:text="@string/stop" /> 17 18 </LinearLayout>
然后修改默認的Activity:

1 public class MainActivity extends Activity implements Runnable { 2 private Thread thread; //聲明線程對象 3 int i; //循環變量 4 5 @Override 6 public void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.main); 9 Button startButton=(Button)findViewById(R.id.button1); //獲取“開始”按鈕 10 startButton.setOnClickListener(new OnClickListener() { 11 12 @Override 13 public void onClick(View v) { 14 i=0; 15 thread=new Thread(MainActivity.this); //創建一個線程 16 thread.start(); //開啟線程 17 18 } 19 }); 20 Button stopButton=(Button)findViewById(R.id.button2); //獲取“停止”按鈕 21 stopButton.setOnClickListener(new OnClickListener() { 22 23 @Override 24 public void onClick(View v) { 25 if(thread!=null){ 26 thread.interrupt(); //中斷線程 27 thread=null; 28 } 29 Log.i("提示:","中斷線程"); 30 31 } 32 }); 33 } 34 35 @Override 36 protected void onDestroy() { 37 38 if(thread!=null){ 39 thread.interrupt(); //中斷線程 40 thread=null; 41 } 42 super.onDestroy(); 43 } 44 @Override 45 public void run() { 46 while(!Thread.currentThread().isInterrupted()){ 47 i++; 48 Log.i("循環變量:",String.valueOf(i)); 49 } 50 51 } 52 }
接下來運行即可。
上面只是線程的簡單操作。這里推薦一篇寫得比較詳細的文章:《java中的多線程》
2、異步消息處理機制
在上面我們已經介紹了線程相關的知識點,不過此時還沒有在新創建的子線程中對UI界面上的內容進行操作,如果用上面的方法進行操作,將會拋出異常。為此,Android中引入了異步消息處理機制,來實現在新創建的線程中操作UI界面。
首先,我們來了解一些概念。
什么是異步?
簡單來說,就是A和B兩個人可以同時做兩種事,也就是分別做自己的事。(而不是A做完事后B才開始做事)
什么是消息處理機制?
就應用程序而言,Android系統中JAVA的應用程序和其他系統上相同,都是靠消息驅動來工作的,他們大致的工作原理如下:
1、有一個消息隊列,可以往這個消息隊列中投遞消息。
2、有一個消息循環,不斷從消息隊列中取出消息,然后處理。
在Android中,一個線程對應一個Looper對象,而一個Looper對象又對應一個MessageQueue(用於存放message)。
接下來,我們來了解幾個類:循環者Looper類,消息處理類Handler,消息類Message。
Looper對象用來為一個線程開啟一個消息循環,用來操作MessgeQueue。默認情況下,Android中新創建的線程是沒有開啟消息循環的。(主線程除外)
消息處理類(Handler)允許發送和處理Message和Rannable對象到其所在線程的MessageQueue中。(它主要有兩個作用:1、將Message或Runnable應用post()方法或sendMessage()方法發送到MessageQueue中,在發送時可以指定延時時間、發送時間或者要攜帶的bundle數據。當MessageQueue循環到該Message時,調用相應的Handler對象的handlerMessage()方法對其進行處理。2、在子線程中與主線程進行通信,也就是在工作線程中與UI線程進行通信。)另外,在一個線程中只能有一個Looper和MessageQueue,但是可以有多個Handler,而且這些Handler可以共享一個Looper和MessageQueue。
消息類(Message)被存放在MessageQueue中,一個MessageQueue中可以包含多個Message對象。每個Message對象可以通過Messhe.obtain()方法或者Handler.obtainMessage()方法獲得。
關系如下圖:
(圖片來源於網絡)
下面我們做一個簡單的實例。(從子線程獲取的數據更新到UI)
布局文件如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/btn" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="點擊改變下方界面"/> <TextView android:id="@+id/tv" android:layout_marginTop="50dp" android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="數據沒改變前"/> </LinearLayout>
java代碼如下:
public class MainActivity extends Activity { private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn=(Button) findViewById(R.id.btn); tv = (TextView) findViewById(R.id.tv); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { Message msg=new Message(); msg.obj="您已點擊按鈕,數據發生改變";//message的內容 msg.what=1;//指定message handler.sendMessage(msg);//handler發送message } }).start(); } }); } private Handler handler=new Handler(){ public void handleMessage(Message msg) { switch (msg.what) { case 1://獲取到what屬性為1的message tv.setText((String)msg.obj);//將message的內容填充到TextView中 break; default: break; } }; }; }
運行程序,結果如下圖:
此外,關於異步消息處理機制。除了handler外,常用的還有AsyncTask。關於AsyncTask請看另一篇博文《Android AsyncTask 初探》。
在子線程中更改UI,更多內容請參考我的另一篇博文《Android 在子線程中更新UI》。
以上三個類關系密切並且方法較多,建議大家參考開發文檔詳細了解:
Looper:http://developer.android.com/intl/zh-cn/reference/android/os/Looper.html
Handler:http://developer.android.com/intl/zh-cn/reference/android/os/Handler.html
message:http://developer.android.com/intl/zh-cn/reference/android/os/Message.html
此外,還有對其三者進行源碼分析的一些相關的博客:
http://www.cnblogs.com/zhaoxiaowei/category/568256.html