1. 程式人生 > >Android執行緒模型--在子執行緒中更新UI

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發訊息的方法實現執行緒間通訊。