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的方法:

扫描二维码关注公众号,回复: 3911031 查看本文章
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发消息的方法实现线程间通信。


猜你喜欢

转载自blog.csdn.net/luckgrilwyy/article/details/50404243
今日推荐