Diferença de setValue () e postValue () em MutableLiveData


105

Existem duas maneiras de alterar o valor de MutableLiveData. Mas qual é a diferença entre setValue()e postValue()em MutableLiveData.

Não consegui encontrar documentação para o mesmo.

Aqui está a aula MutableLiveDatade Android.

package android.arch.lifecycle;

/**
 * {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} method.
 *
 * @param <T> The type of data hold by this instance
 */
@SuppressWarnings("WeakerAccess")
public class MutableLiveData<T> extends LiveData<T> {
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

Respostas:


178

Com base na documentação:

setValue () :

Define o valor. Se houver observadores ativos, o valor será despachado para eles. Este método deve ser chamado a partir do thread principal.

postValue () :

Publica uma tarefa em um thread principal para definir o valor fornecido. Se você chamar esse método várias vezes antes de um thread principal executar uma tarefa postada, apenas o último valor será despachado.

Para resumir, a principal diferença seria:

setValue()método deve ser chamado a partir do thread principal. Mas se você precisar definir um valor de um thread de segundo plano, postValue()deve ser usado.


"apenas o último valor seria despachado". Não posso ter certeza sobre isso lendo o código. Portanto, parece que quando o primeiro thread está prestes a atingir o bloco sincronizado interno dentro de postValue (), a próxima janela da CPU pode ser potencialmente fornecida ao thread 2 que está postando outro valor. O thread 2 pode então completar o bloco sincronizado e o planejador dá ao primeiro thread uma janela para ser executado. Agora, ele sobrescreve o que o thread 2 já escreveu. Isso é possível?
stdout

97

Todas as respostas acima estão corretas. Mas mais uma diferença importante. Se você chamar postValue()em um campo que não tem observadores e depois ligar getValue(), você não receberá o valor que definiu em postValue(). Portanto, tome cuidado se você trabalhar em threads de fundo sem observadores.


3
Gostaria de poder triplicar o voto! Com base nisso, parece que é melhor usar, setValue()se possível, e usar 'postValue ()' com cautela, apenas quando necessário. Obrigado
jungledev

1
Não, aqui não existe nenhuma "melhor" maneira. Se você trabalha com seu LiveData a partir de um thread de segundo plano, deve usar postValue. Também na última versão dos componentes do ciclo de vida, ele corrigiu ... provavelmente.
w201

"Também na última versão dos componentes do ciclo de vida, ela corrigiu ... provavelmente." Você tem mais informações sobre isso? Obrigado
Chris Nevill

1
Fiz alguns testes e parece que com a última versão do lib tudo funciona como deveria.
w201

Você poderia me mostrar o código acima de forma concreta? Se em ViewModel, implementei como noObserveLiveData.postValue("sample"), em atividade, quando usei getValue como viewModel.noObserveLiveData.getValueVocê quer dizer que não é o valor que defini em postValue () ("amostra")?
kwmt

14

setValue()é chamado diretamente do thread do chamador, notifica os observadores de forma síncrona e altera o LiveDatavalor imediatamente. Ele pode ser chamado apenas a partir de MainThread.
postValue()usa dentro de algo como isso new Handler(Looper.mainLooper()).post(() -> setValue()), então ele é executado setValueatravés Handlerde MainThread. Ele pode ser chamado de qualquer thread.


11

setValue()

Define o valor. Se houver observadores ativos, o valor será despachado para eles.

Este método deve ser chamado a partir do thread principal .

postValue

Se você precisar definir um valor de um thread de segundo plano, você pode usar postValue(Object)

Publica uma tarefa em um thread principal para definir o valor fornecido.

Se você chamar esse método várias vezes antes de um thread principal executar uma tarefa postada, apenas o último valor será despachado.


5

Esta não é uma resposta direta ao problema acima. As respostas de Sagar e w201 são fantásticas. Mas uma regra prática simples que uso em ViewModels para MutableLiveData é:

private boolean isMainThread() {
    return Looper.myLooper() == Looper.getMainLooper();
}

private MutableLiveData<Boolean> mutVal = new MutableLiveData<>(false);
public LiveData<Boolean> getMutVal() { return this.mutVal;  }
public void setMutVal(boolean val) {
    if (isMainThread()) mutVal.setValue(val);
    else mutVal.postValue(val);
}

Substitua mutValpelo valor desejado.


Legal, eu gosto disso. Em Kotlin, criei uma extensão que encapsula a atualização inteligente para que as inúmeras atualizações de valor em todo o meu aplicativo sejam uma chamada única e consistente.
19Craig

4

setValue()método deve ser chamado a partir do thread principal. Se você precisar definir um valor de um thread de segundo plano, você pode usarpostValue() .

Mais aqui .


0

Em nosso aplicativo, usamos um LiveData único que contém dados para várias visualizações em uma atividade / tela. Basicamente, N não de conjuntos de dados para N de visualizações. Isso nos incomodou um pouco, devido à forma como o postData foi projetado. E temos objeto de estado em LD que transmite a visão sobre qual visão precisa ser atualizada.

então LD se parece com isto:

LD {
   state (view_1, view_2, view_3 …),
   model_that_contains_data_of_all_views
}

Existem algumas visualizações (view_1 e view_2) que tiveram que ser atualizadas quando um evento ocorre ... significa que elas devem ser notificadas ao mesmo tempo quando o evento ocorre. Então, liguei:

postData(LD(view_1, data))
postData(LD(view_2, data)

Isso não funcionaria por razões que conhecemos.

O que entendi é que basicamente um LD deve representar apenas uma visão. Então, não há chance de você ter que chamar postData () duas vezes seguidas. Mesmo se você chamar, a maneira como postData lida com isso para você é o que você também esperaria (mostrando os dados mais recentes para você na visualização). Tudo cai bem no lugar.

Um LD -> uma Visualização. PERFEITO

Um LD -> visualizações múltiplas PODE EXISTIR UM COMPORTAMENTO ESTRANHO

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.