android 线程更新UI的问题

子线程更新UI

大多数说法是子线程更新UI会出现 CalledFromWrongThreadException的异常,但在偶然情况下发现并不是这样.具体情况如下:

抛出异常的类和方法: ViewRootImpl:checkThread

ViewRootImpl.java

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

此方法在ViewRootImpl中的RequestLayout方法中调用:

   @Override
    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }

而ViewRootImpl会在onCreate方法之后初始化,所以在onCreate方法中立即开启主线程调用是不会出问题的,但如果线程sleep一段时间就会抛出异常:

        new Thread(new Runnable() {
            @Override
            public void run() {
//                try {
//                    Thread.sleep(3000);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
                tv_flextv1.setText("change thread");
//                tv_flextv1.setBackgroundColor(getResources().getColor(R.color.design_default_color_primary));
            }
        }).start();

另一个证明的例子是如果在点击事件里面使用子线程更新UI会立即抛出异常.此外requestLayout方法调用的时机是布局大小改变,如果设置背景色等不会调用,由于setTest的控件是自适应大小的,所以会调用requestLayout.
ViewRootImpl 是View包括子类ViewGroup一些方法的具体实现,类接口ViewParent由它实例化.只属于根布局的.

posted @ 2022-04-13 13:56  百密一疏  阅读(231)  评论(0编辑  收藏  举报