我們知道在Android中,要更新UI只能在UI主線程去更新,而不允許在子線程直接去操作UI,但是很多時候,很多耗時的工作都交給子線程去實現,當子線程執行完這些耗時的工作后,我們希望去修改UI,但Android中又不允許在子線程中去直接修改UI,如:在子線程中執行從服務器下載一張圖片的任務,下載完成后,希望這張圖片顯示一個ImageView上,在子線程中又不能直接操作ImageView,這怎么辦呢?我們只能把這張圖片發送給UI主線程,然后在主線程中去顯示這張圖片。為了能夠實現這種子線程和主線程之間的數據交換,Android提供了異步消息處理機制來解決這個問題。Android的異步消息處理機制如:Handler異步消息處理機制和AsyncTask異步任務(內部實現也是基於異步消息處理機制)。Handler異步消息處理機制由Message,Handler,MessageQueue和Looper四個部分組成。
一. 先看Android中啟動子線程的方法:
例子:創建和啟動子線程的三個方法,Android中多線程的寫法和Java多線程寫法基本上都是一樣的。
(1)布局文件內容:三個按鈕,分別用於啟動三個子線程
1 <LinearLayout 2 xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" 6 tools:context=".MainActivity" 7 android:orientation="vertical" 8 > 9 10 <Button 11 android:id="@+id/button01" 12 android:layout_width="match_parent" 13 android:layout_height="wrap_content" 14 android:text="第一種方式啟動子線程" 15 /> 16 17 <Button 18 android:id="@+id/button02" 19 android:layout_width="match_parent" 20 android:layout_height="wrap_content" 21 android:text="第二種方式啟動子線程" 22 /> 23 24 <Button 25 android:id="@+id/button03" 26 android:layout_width="match_parent" 27 android:layout_height="wrap_content" 28 android:text="第三種方式啟動子線程" 29 /> 30 31 </LinearLayout>
(2) MainActivity:先打印出主線程的ID,分別點擊三個按鈕,啟動三個不同的子線程,在子線程分別打印出子線程的ID
1 package zst.zst.thread01; 2 import java.util.TreeMap; 3 import android.os.Bundle; 4 import android.app.Activity; 5 import android.view.View; 6 import android.view.View.OnClickListener; 7 import android.widget.Button; 8 public class MainActivity extends Activity implements OnClickListener{ 9 private Button button01; 10 private Button button02; 11 private Button button03; 12 13 @Override 14 protected void onCreate(Bundle savedInstanceState) { 15 super.onCreate(savedInstanceState); 16 setContentView(R.layout.activity_main); 17 button01 = (Button)findViewById(R.id.button01); 18 button02 = (Button)findViewById(R.id.button02); 19 button03 = (Button)findViewById(R.id.button03); 20 button01.setOnClickListener(this); 21 button02.setOnClickListener(this); 22 button03.setOnClickListener(this); 23 24 //主線程ID 25 System.out.println("主線程的ID-----> " + String.valueOf(Thread.currentThread().getId())); 26 } 27 @Override 28 public void onClick(View v) { 29 switch (v.getId()) { 30 case R.id.button01: 31 //第一種啟動子線程的方法 32 FirstThread firstThread = new FirstThread(); 33 firstThread.start(); 34 35 break; 36 case R.id.button02: 37 //第二種啟動子線程的方法 38 SecondThread secondThread = new SecondThread(); 39 new Thread(secondThread).start(); 40 41 break; 42 case R.id.button03: 43 //第三種啟動子線程的方法,和第二種方法是同一種啟動方法,只不過這里用匿名內部類,這種方法最常見 44 new Thread(new Runnable() { 45 46 @Override 47 public void run() { 48 System.out.println("第三個子線程的ID---> " + String.valueOf(Thread.currentThread().getId())); 49 } 50 }).start(); 51 52 break; 53 default: 54 break; 55 } 56 57 } 58 //第一種方法定義一個線程 59 class FirstThread extends Thread{ 60 @Override 61 public void run() { 62 System.out.println("第一個子線程的ID---> " + String.valueOf(Thread.currentThread().getId())); 63 } 64 65 66 } 67 68 //第二種方法定義一個線程 69 class SecondThread implements Runnable{ 70 @Override 71 public void run() { 72 System.out.println("第二個子線程的ID---> " + String.valueOf(Thread.currentThread().getId())); 73 } 74 75 } 76 77 78 }
(3)
輸出:
