Android学习笔记·子线程&UI

1,162 阅读1分钟

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()方法之后才被创建的,所以上面的代码是可以通过编译以及运行的。