Android執行緒模型--在子執行緒中更新UI
Android是支援多執行緒的。主執行緒也稱UI執行緒,子執行緒也稱工作執行緒。一般耗時操作在子執行緒中進行,更新UI操作在主執行緒中進行。在主執行緒中執行耗時操作容易發生ANR錯誤,即應用程式無響應。而Android中又規定只有建立UI的執行緒才能更新UI,即只有主執行緒才能更新UI。然後,我們又聽說有什麼方法可以子執行緒中也可以更新UI。
在子執行緒中更新UI的方法有:
1)Activity類:public void runOnUiThread(Runable action);
2)View類:public boolean post(Runable action);
3)View類:public boolean postDelayed(Runable action,long delayMillis);
可是AndroidUI執行緒模型不是明確表示子執行緒中不能更新UI嗎?這是怎麼回事?結合例子,我們來看一下。
第一種在子執行緒中更新UI的方法:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ivImage=(ImageView) findViewById(R.id.imageView1); //handler=new InnerHandler(); handler=new Handler(new InnerCallback()); } public class InnerCallback implements Handler.Callback{ @Override public boolean handleMessage(Message msg) { if(msg.what==LOAD_IMAGE_COMPLETED){ ivImage.setImageBitmap(bm); } return false; } }
--------------------------------------------------------------------------
第二種在子執行緒中更新UI的方法:
public void doLoadImage(View v){ //子執行緒呼叫View的post()方法更新ui new Thread(){ public void run() { //從網路中載入圖片,即耗時操作 final Bitmap bm=loadImageFromNetwork(); ivImage.post(new Runnable() { @Override public void run() { //更新圖片顯示 ivImage.setImageBitmap(bm); } }); }; }.start(); }
第三種與第二種類似。
子執行緒是不允許更新UI的,而這些方法從原始碼的角度似乎是在子執行緒中更新UI,其實是間接的呼叫的主執行緒更新UI,並不是真的在子執行緒中更新UI。其主執行緒與子執行緒之間的通訊採用的是訊息機制。
檢視其原始碼可知,
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
---------------------------------------------------------
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);
return true;
}
本質上都是呼叫了Handler中的post()實現執行緒間通訊,而Handler的post()系列方法使用Runnable作為引數,其實質還是呼叫Handler發訊息的方法實現執行緒間通訊。