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