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发消息的方法实现线程间通信。