每個Android應用程式都運行在一個dalvik虛擬機器進程中,進程開始的時候會啟動一個主線程(MainThread),主線程負責處理和ui相關的事件,因此主線程通常又叫UI線程。而由於Android採用UI單執行緒模式,所以只能在主線程中對UI元素進行操作。如果在非UI線程直接對UI進行了操作,則會報錯:CalledFromWrongThreadException:only the original thread that created a view hierarchy can touch its views。Android為我們提供了訊息迴圈的機制,我們可以利用這個機制來實現線程間的通訊。那麼,我們就可以在非UI線程發送訊息到UI線程,最終讓Ui線程來進行ui的操作。對於運算量較大的操作和IO操作,我們需要新開線程來處理這些繁重的工作,以免阻塞ui線程。 ThreadHandlerActivity.activity[java] public class ThreadHandlerActivity extends Activity { /** Called when the activity is first created. */ private static final int MSG_SUCCESS = 0;//擷取圖片成功的標識 private static final int MSG_FAILURE = 1;//擷取圖片失敗的標識 private ImageView mImageView; private Button mButton; private Thread mThread; private Handler mHandler = new Handler() { public void handleMessage (Message msg) {//此方法在ui線程運行 switch(msg.what) { case MSG_SUCCESS: mImageView.setImageBitmap((Bitmap) msg.obj);//imageview顯示從網路擷取到的logo Toast.makeText(getApplication(), "成功!", Toast.LENGTH_LONG).show(); break; case MSG_FAILURE: Toast.makeText(getApplication(), "失敗!", Toast.LENGTH_LONG).show(); break; } } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.threadhandler); mImageView= (ImageView) findViewById(R.id.threadhandler_imageView);//顯示圖片的ImageView mButton = (Button) findViewById(R.id.threadhandler_download_btn); mButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if(mThread == null) { mThread = new Thread(runnable); mThread.start();//線程啟動 } else { Toast.makeText(ThreadHandlerActivity.this, "線程已啟動!", Toast.LENGTH_LONG).show(); } } }); } Runnable runnable = new Runnable() { @Override public void run() {//run()在新的線程中運行 HttpClient hc = new DefaultHttpClient(); HttpGet hg = new HttpGet("http://pic7.nipic.com/20100517/4945412_113951650422_2.jpg");//擷取指南針圖片 final Bitmap bm; try { HttpResponse hr = hc.execute(hg); bm = BitmapFactory.decodeStream(hr.getEntity().getContent()); } catch (Exception e) { mHandler.obtainMessage(MSG_FAILURE).sendToTarget();//擷取圖片失敗 return; } mHandler.obtainMessage(MSG_SUCCESS,bm).sendToTarget();//擷取圖片成功,向ui線程發送MSG_SUCCESS標識和bitmap對象 } }; } threadhandler.xml [html] <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/threadhandler_download_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="ThreadHandler下載" > </Button> <ImageView android:id="@+id/threadhandler_imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> 運行結果: 非UI線程發送訊息到UI線程分為兩個步驟一、發送訊息到UI線程的訊息佇列通過使用Handler的Message obtainMessage(int what,Object object)構造一個Message對象,這個Object Storage Service了是否成功擷取圖片的標識what和bitmap對象,然後通過message.sendToTarget()方法把這條message放到訊息佇列中去。二、處理髮送到UI線程的訊息在ui線程中,我們覆蓋了handler的 public void handleMessage (Message msg) 這個方法是處理分發給ui線程的訊息,判斷msg.what的值可以知道mThread是否成功擷取圖片,如果圖片成功擷取,那麼可以通過msg.obj擷取到這個對象。最後,我們通過mImageView.setImageBitmap((Bitmap) msg.obj);設定ImageView的bitmap對象,完成UI的更新。