Android: The reason why the child thread in the Activity.OnCreate method can update the UI, and the reason why the UI cannot be updated after sleep


Find the answer from the source code: Just find an update operation of the UI control, such as the setText operation of TextView and then track:

In the TextView class:

private void setText(CharSequence text, BufferType type,
                         boolean notifyBefore, int oldlen) {
        ...
        if (mLayout != null) {
            checkForRelayout();//调用
        }
        ...
    }
    
    /**
     * 检查全新的文本是否需要新的视图布局
     * 或者只是一个新的文本布局
     */
    private void checkForRelayout() {
    //无论如何都会执行下面两行代码
            ...
            requestLayout();//重新请求布局
            invalidate();//重绘
            ...
    }

Finally, invalidate () calls the invalidate method in View

In the View class:

public void invalidate() {// 1
        invalidate(true);
    }
    
    public void invalidate(boolean invalidateCache) {// 2
        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
    }
    
    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
            boolean fullInvalidate) {// 3
            ...
            final ViewParent p = mParent;
            if (p != null && ai != null && l < r && t < b) {
                p.invalidateChild(this, damage);
            }
            //调用ViewParent 接口的 invalidateChild方法,该接口被ViewRootImpl实现,
            //并且最终会调用ViewRootImpl的 invalidateChild方法
            //直接去看ViewRootImpl的 invalidateChild方法
            ...
    }
    
    

Remember this if condition, where ViewParent is implemented by ViewRootImpl. And made a judgment that it is not empty program will continue, because mParent is assigned in the Activity onResume method. So it is empty during onCreate. This is why subthreads can refresh the UI in onCreate.

In ViewRootImpl class:

    public void invalidateChild(View child, Rect dirty) { // 1
        invalidateChildInParent(null, dirty);
    }
    
    public ViewParent invalidateChildInParent(int[] location, Rect dirty) { // 2
        checkThread();
        ...
    }
    
    void checkThread() { // 3 在这里 判断并抛出异常
        if (mThread != Thread.currentThread()) {
            throw new CalledFromWrongThreadException(
                    "Only the original thread that created a view hierarchy can touch its views.");
        }
    }
    

Yes, that's right, the final and final point is to judge and throw an exception here. Because there is a judgment on the ViewParent implementation class in View, it will be executed here when it is not empty, and ViewParent will be assigned in the OnResume method of the Activity life cycle. Therefore, if you use a child thread in the onCreate method, you can do a wave of update UI operations. The thread schedules a random relationship in the CPU. When the child thread reaches this judgment, the main thread may not create a ViewParent and assign a value.

Published 60 original articles · 25 praises · 10,000+ views

Guess you like

Origin blog.csdn.net/qq_41466437/article/details/105218834