Pesquisa sobre o código-fonte LiveData do MVVM do Android

        O padrão MVVM fornecido oficialmente pelo Android consiste em DataBinding, ViewModel e LiveData.

        Sem mais delongas, vamos ver como o LiveData é usado?

class TestActivity : AppCompatActivity() {

    private var data: MutableLiveData<String> = MutableLiveData()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_test)

        // 通过 observe LiveData 数据
        data.observe(this, object : Observer<String> {

            // 通过 observe 回调 数据
            override fun onChanged(t: String?) {
                Timber.tag("MyTest").d(t)
            }

        })
        
        button.setOnClickListener {
            /**
             * 通过 postValue / setValue 设置数据
             * setValue() 必须在主线程
             * postValue() 在哪个线程设置都可以 最终还是通过 setValue() 设置的
             * */ 
            data.postValue("postValue12345")
            data.setValue("setValue12345")
        }
    }
}

        LiveData é uma classe abstrata e não pode criar uma instância, então use sua subclasse MutableLiveData para criar um LiveData.

        Obviamente, este é um padrão de observador. LiveData registra os dados de monitoramento por meio de observe() e define os dados por meio de setValue / postValue. Na verdade, postValue() é finalmente definido por setValue(). Amigos que o usaram acreditam que todos o conhecem.

        Mas este artigo não é para ver como usá-lo, mas para explorar o código-fonte do LiveData para ver como ele está vinculado ao ciclo de vida do host.

        Ok, vamos olhar o código fonte com   4   perguntas:

        【Pergunta 1】: Como destruir a atividade do host ou Framgent sem cancelar manualmente o monitoramento?

        [ Questão 2 ]: Como enviar novos dados para o ouvinte apenas quando o host Activity ou Framgent está visível?

        [ Pergunta 3 ]: Como definir os dados quando a atividade do host ou Framgent não está visível e não enviar os novos dados para o ouvinte imediatamente e, em seguida, enviar os novos dados para o ouvinte quando a atividade ou Framgent estiver visível novamente?

        [ Questão 4 ]: Como enviar dados para o observador somente quando os dados forem atualizados novamente quando a Atividade do host ou Framgent estiver visível novamente, e o ouvinte não será notificado se os dados não tiverem sido atualizados

------------------- Parte 1 -------------------------

Em primeiro lugar, vamos ver qual lógica é feita ao registrar para monitorar e observar o código-fonte de LiveData.observe()

    

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer){
        // ---------------注释1 ---------------
        assertMainThread("observe");
        // ---------------注释2 ---------------
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }

        //  注释3 这个是重点 大部分逻辑在这个 LifecycleBoundObserver 里面
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);

        // ---------------注释4 ---------------
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }

        // ---------------注释5 ---------------
        owner.getLifecycle().addObserver(wrapper);
    }

[ Nota 1 ]: A detecção deve ser monitorada no thread principal, caso contrário, uma exceção será lançada, portanto, o monitoramento do LiveData deve ser no thread principal. Os alunos interessados ​​podem entrar e dar uma olhada. O código interno é muito simples

[ Nota 2 ]: Se o LifecycleOwner do host atual (ou seja: Activity / Framgent) já estiver no estado de destruição, não há necessidade de se registrar para monitoramento e sair diretamente. Essa lógica não precisa de explicação

[ Nota 3 ]: Vincule o LifecycleOwner e o Observer do LiveData através do LifecycleBoundObserver, para que o ciclo de vida do LifecycleOwner e do Observer do LiveData possam ser vinculados.

Observação 4】: Salve o ouvinte LiveData criado em mObservers. Quando houver uma alteração de dados posteriormente, cada elemento de mObservers será percorrido e novos dados serão enviados para ouvintes qualificados, um por um.

[ Nota 5 ]: LifecycleOwner monitora o ciclo de vida, e os retornos de chamada para alterações no estado do ciclo de vida são todos chamados de volta em LifecycleBoundObserver.

Portanto, para resumir esta parte, LifecycleBoundObserver vincula os ouvintes LifecycleOwner e LiveData, para que os ouvintes possam perceber o ciclo de vida da Atividade/Fragmento.

------------------- Parte 2 ------------------------

Vamos apenas olhar para o LifecycleBoundObserver mencionado acima e ver como este LifecycleBoundObserver é implementado

    class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {

        //省略无关紧要的代码.....................

        @Override
        boolean shouldBeActive() {
            // 这里的意思是只有在LifecycleOwner(Activity / Fragment) 可见时才会返回 true
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        // ----------------注释1---------------
        @Override
        public void onStateChanged(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            // ----------------注释2---------------
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            // ----------------注释3---------------
            activeStateChanged(shouldBeActive());
        }

        //省略无关紧要的代码.....................
    }



    private abstract class ObserverWrapper {

    	//省略无关紧要的代码.....................
       
        
        void activeStateChanged(boolean newActive) {
            // 状态和之前一样不执行,这个很合理
            if (newActive == mActive) {
                return;
            }
            mActive = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                // 空实现,可以重写此方法自己执行自己的拓展业务逻辑
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                // 同样空实现,可以重写此方法自己执行自己的拓展业务逻辑
                onInactive();
            }
            if (mActive) {
                // ----------------注释4--------------- 
                dispatchingValue(this);
            }
        }
    }

Omitindo algum código irrelevante, você pode ver que LifecycleBoundObserver está integrado no ObserverWrapper e implementa a interface LifecycleEventObserver.

[ Nota 1 ]: Alterações no ciclo de vida do host LifecycleOwner (ou seja: Activity / Framgent) serão chamadas de volta por meio do método onStateChanged() da Nota 1, que é a função de [ Parte 1 ] Nota 5 owner.getLifecycle() .addObserver(wrapper)

[ Nota 2 ]: Quando o ciclo de vida do host LifecycleOwner (ou seja: Activity / Framgent) for destruído, o listener será removido. Esta [ Parte 1 ] Nota 4 corresponde ao monitoramento e cancelamento do modo observador. Isso explica nossa [ Pergunta 1 ] (Como destruir a atividade do host ou Framgent sem cancelar manualmente o monitor?)

[ Nota 3 ]: A mudança de estado finalmente chama activeStateChanged() .Este método está no ObserverWrapper, a classe pai de LifecycleBoundObserver.A lógica aqui é clara a partir do código da classe pai. Mas é passado um parâmetro aqui, que é obtido através do shouldBeActive() , os alunos que tiverem interesse na lógica interna podem entrar e dar uma olhada por conta própria, ou seja, retornará true somente quando o LifecycleOwner (ou seja: Activity / Framgent) é visível.

[ Nota 4 ]: Por fim, dispatchingValue() notifica o listener, mas existe uma condição aqui, ou seja, este método só será executado quando o parâmetro de entrada newActive for verdadeiro. Obviamente, este newActive é passado da Nota 3, que ou seja, LifecycleOwner ( Ou seja: Activity / Framgent) será true quando estiver visível, e dispatchingValue() será executado para notificar o ouvinte. Isso é [ Question 2 ] e [ Question 3 ]. Se não estiver visível, não será notificado e, se ficar visível novamente, será notificado novamente.

Bem, aqui é onde podemos facilmente levar a uma pergunta: notificamos o observador toda vez que nossa Activity / Framgent se torna visível novamente? É razoável notificar quando houver alteração nos dados, não havendo necessidade de notificar quando não houver alteração. Este é o nosso problema [ Questão 4 ]. Na verdade, eles estão todos no método dispatchingValue()  mencionado acima

------------------- Parte 3 ------------------------

Ok, vamos dar uma olhada na lógica dentro dispatchingValue()

    void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                //--------注释1 执行通知
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    //--------注释2 执行通知
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }



   private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        // ----- 注释3 当前 Version 是否已经发送过,发送过退出不需要发送
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        // ----- 注释4 保存当前 Version 表示当前数据已经发送给观察者了 
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }

Na verdade, dispatchingValue()  é para percorrer todos os observadores, enviar dados para os observadores, principalmente ver [ Nota 1 ] e [ Nota 2 ], que é executar e enviar para os observadores, mas essa etapa ainda não nos vê [ Questão 4 ] Responder.

Vamos inserir o método considerNotify() inserido em [ Nota 1 ] e [ Nota 2 ] , e podemos ver [ Nota 3 ] e [ Nota 4 ], que serve para julgar se os dados atuais foram enviados.  está definido, procure a referência e você verá que está definido durante LiveData.setValue(). Como postValue() é finalmente definido por meio de setValue(), qualquer método usado para definir os dados será executado em LiveData.setValue().

    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

É claro de relance,,,,,,,,,

Então [ Questão 4 ] Todo o processo é: cada LiveDate corresponde a salvar uma Versão, e cada vez que o LiveDate for definido, a Versão correspondente será incrementada em 1. Quando os dados forem enviados ao observador, a Versão será salva. Quando a Atividade retornar de invisível para visível, ela julgará se a Versão salva é consistente com a Versão do LiveDate. Se for consistente, significa que os dados já foram enviados para o observador, e não serão enviados novamente de forma redundante. Apenas quando for inconsistente Só então novos dados serão enviados ao observador. É por isso que Activity/Fragment só enviará os mesmos dados para o observador uma vez, mesmo que retorne de invisível para visível várias vezes. Esta é a resposta para a [ Pergunta 4 ] que estamos procurando .

Se a lógica do código acima estiver errada, deixe uma mensagem para apontar, obrigado

Acho que você gosta

Origin blog.csdn.net/Leo_Liang_jie/article/details/120435596
Recomendado
Clasificación