Android原生开发中,避免不了在子线程实现UI更新这个问题,下面记录子线程更新UI相关的知识点。
常见的子线程更新UI的方法:
1、在Activity、Fragment中:
new Thread(new Runnable() {
@Override
public void run() {
//TODO...子线程计算结果
runOnUiThread(new Runnable() {
@Override
public void run() {
//TODO...UI线程更新UI
}
});
}
});原理顾名思义是通过主线程更新UI。
2、非Activity或者Fragment中:
new Thread(new Runnable() {
@Override
public void run() {
//TODO...子线程计算结果
Looper.prepare();
//TODO...更新UI
Looper.loop();
}
});原理为在子线程直接创建ViewRootImpl对象,通过WindowManager操作View。
注意:Loop()方法后的代码,将不会被执行。
3、非Activity或者Fragment中:
//仅为演示,实际开发需要为Handler创建静态画实例
final Handler handler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg){
//TODO 根据结果更新UI
super.handleMessage(msg);
}};
new Thread(new Runnable() {
@Override
public void run() {
//TODO 计算结果
Message message = handler.obtainMessage();
message.what = 0;
message.obj = new Object();//计算结果
handler.sendMessage(message);
}
});原理是通过Handler通过消息队列通知主线程更新UI。
4、还有一种不常用但是理论存在的更新方式:
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new Thread(new Runnable() {
@Override
public void run() {
//TODO 直接操作UI
}
}
)}这种写法是没问题的,那么为什么呢?
其原理是在Activity创建后,ViewRootImpl的实例还未初始化,
ViewRootImpl中的checkThread()方法是检查操作UI的线程是否为创建ViewRootImpl实例的线程。
ViewRootImpl的创建是在Activity的onResume()方法之后才被创建的,所以上面的代码是可以通过编译以及运行的。
