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.