Android: o motivo pelo qual o thread filho no método Activity.OnCreate pode atualizar a interface do usuário e o motivo pelo qual a interface do usuário não pode ser atualizada após o sono


Encontre a resposta no código-fonte: encontre uma operação de atualização do controle da interface do usuário, como a operação setText do TextView e, em seguida, acompanhe:

Na classe TextView:

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

Por fim, invalidate () chama o método invalidate em View

Na classe View:

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方法
            ...
    }
    
    

Lembre-se desta condição, se o ViewParent for implementado pelo ViewRootImpl. E julgou que o programa não está vazio continuará, porque o mParent é atribuído no método Activity onResume. Portanto, ele está vazio durante o onCreate. É por isso que os sub-roscas podem atualizar a interface do usuário no onCreate.

Na classe ViewRootImpl:

    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.");
        }
    }
    

Sim, isso mesmo, o ponto final e final é julgar e lançar uma exceção aqui. Como existe um julgamento sobre a classe de implementação ViewParent no View, ela será executada aqui quando não estiver vazia e o ViewParent será atribuído no método OnResume do ciclo de vida da Atividade. Portanto, se você usar um thread filho no método onCreate, poderá executar uma onda de operações de atualização da interface do usuário. O encadeamento agenda um relacionamento aleatório na CPU. Quando o encadeamento filho atinge esse julgamento, o encadeamento principal pode não criar um ViewParent e atribuir um valor.

Publicado 60 artigos originais · 25 elogios · 10.000+ visualizações

Acho que você gosta

Origin blog.csdn.net/qq_41466437/article/details/105218834
Recomendado
Clasificación