android程式與執行緒詳解二:執行緒

yangxi_001發表於2013-11-19

執行緒


當一個應用被啟動,系統建立一個執行執行緒,叫做"main"。這個執行緒是十分重要的,因為它主管向使用者介面控制元件派發事件。其中包含繪圖事件。它也是你的應用與介面工具包(android.widgetandroid.view包中的元件)互動的地方。於是main執行緒也被稱為介面執行緒。


系統不會為每個元件的例項分別建立執行緒。所有執行於一個程式的元件都在介面執行緒中被例項化,並且系統對每個元件的呼叫都在這個執行緒中派發。 結果,響應系統呼叫的方法(比如報告使用者動作的onKeyDown()或一個生命週期回撥方法)永遠在介面執行緒中進行。


例如,當使用者觸控螢幕上的一個按鈕時,你的應用的介面執行緒把觸控事件派發給控制元件,然後控制元件設定它的按下狀態再向事件佇列發出一個自己介面變得無效的請求,介面執行緒從佇列中取出這個請求並通知這個控制元件重繪它自己。


當你的應用在響應使用者互動時需執行大量運算時,這種單執行緒的模式會帶來低效能,除非你能正確的優化你的程式。特別的,如果所有事情都在介面執行緒中發生,執行比如網路連線或資料庫請求這樣的耗時操作,將會阻止整個介面的響應。當執行緒被阻塞時,就不能派發事件了,包括繪圖事件。從使用者的角度看,程式反應太慢了。甚至更糟的是,如果介面執行緒被阻塞幾秒鐘(大5秒鐘吧),使用者就戶抱怨說程式沒反應了,使用者可能因而退出並刪掉你的應用。


此外,Andoid介面不是執行緒安全的。所以你絕不能在一個工作執行緒中操作你的介面—你只能在介面執行緒中管理的你的介面。所以,對於單執行緒模式有兩個簡單的規則:

1不要阻塞介面執行緒

2不要在介面執行緒之外操作介面。


工作執行緒

由於上述的單執行緒模式,不要阻塞你的介面執行緒以使你的應用的介面保持響應是非常重要的,那麼如果你有不能很快完成的任務,你應把它們放在另一個執行緒中執行(後臺執行緒或工作執行緒)

例如,下面是的程式碼是響應click事件,在另外一個執行緒中下載一個圖片並在一個ImageView中顯示它:

[java] view plaincopy
  1. public void onClick(View v) {  
  2.     new Thread(new Runnable() {  
  3.         public void run() {  
  4.             Bitmap b = loadImageFromNetwork("http://example.com/image.png");  
  5.             mImageView.setImageBitmap(b);  
  6.         }  
  7.     }).start();  
  8. }  

第一眼,這看起來能很好的工作,因為它建立了一個新執行緒來進行網路操作。然而它違反了第二條規則:不要在介面執行緒之外操作介面—它簡單的在工作執行緒中修改了ImageView。這會導至未定義的異常出現,並且難以除錯追蹤。


為了能改正這個問題,Android提供了很多從其它執行緒來操作介面的方法。下面是可用的方法們:

1 Activity.runOnUiThread(Runnable)

2 View.post(Runnable)

3 View.postDelayed(Runnable,long)


例如,你可以用View.post(Runnable)來修正上面的問題:

[java] view plaincopy
  1. public void onClick(View v) {  
  2.     new Thread(new Runnable() {  
  3.         public void run() {  
  4.             final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");  
  5.             mImageView.post(new Runnable() {  
  6.                 public void run() {  
  7.                     mImageView.setImageBitmap(bitmap);  
  8.                 }  
  9.             });  
  10.         }  
  11.     }).start();  
  12. }  

現在這個實現終於是執行緒安全的了:網路操作在另一個執行緒中並且ImageView在介面執行緒中改變。

相關文章