Android系列:什么是UI线程,它是怎么启动的

2,321 阅读2分钟

1.什么是UI线程?UI线程等于主线程吗?

1.1 Activity#runOnUiThread

如果当前的应用组件是Activity,我们经常在子线程里面刷新ui的时候会这样操作

public final void runOnUiThread(Runnable action) {
        if (Thread.currentThread() != mUiThread) {
            mHandler.post(action);
        } else {
            action.run();
        }
    }
    
    //Activity启动的时候会创建,这些是在主线程
     final void attach(Context context){
         mUiThread = Thread.currentThread();
     }

从上面可以看出,==mUiThread是创建Activity的时候attach所在的线程==,所以ui线程就是主线程。

1.2 View.post

    public boolean post(Runnable action) {
        final AttachInfo attachInfo = mAttachInfo;
        if (attachInfo != null) {
            return attachInfo.mHandler.post(action);
        }

        // Postpone the runnable until we know on which thread it needs to run.
        // Assume that the runnable will be successfully placed after attach.
        //有可能ViewRootImpl还没有创建好
        getRunQueue().post(action);
        return true;
    }
    
     /**
         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
         * handler can be used to pump events in the UI events queue.
         */
        final Handler mHandler;

这里的AttachInfo 是在ViewRootImpl创建的时候创建的,所以是在主线程, mHandler是在主线程中创建的Handler,所以刷新ui也会切换到主线程中去。==对于View来说,它的UI线程就是ViewRootImpl所在的线程==,如果不在这个线程去刷新ui就会抛异常

1.3 UI线程是怎么启动的

就是ActivityThread的main()的启动,涉及到消息循环。

  • 说说UI线程是什么?

  • UI消息循环是怎么创建的?

    可以简单说说应用进程是怎么启动的
    
  • UI线程和UI体系之间的关系

     谈谈ViewRootImpl
    

一定切记不是说不能在子线程中去刷新ui,如下例子:

new Thread(){
    
    public void run(){
        Looper.prepare();
        getWindowManager.addView(view, params);
        Looper.loop();
    }
}.start()

这个例子中,我们就是在子线程中去添加View到DecorView,这时候刷新ui就应该在子线程中了,在主线程中刷新ui反而会抛异常。

    void checkThread() {
        if (mThread != Thread.currentThread()) {
            throw new CalledFromWrongThreadException(
                    "Only the original thread that created a view hierarchy can touch its views.");
        }
    }

==我们一定要劳记这个异常的本质。本质就是,刷新当前ui的线程必须和添加当前ui的线程保持一致,也就是说,如果你的ui是在主线程中添加的(例如常规的Activity中的ui),那么你就在主线程中去刷新,反之,你的ui是在子线程中添加的(例如上面的例子),那么你就需要在子线程中去刷新。==系列线程