Differenza di setValue () e postValue () in MutableLiveData


105

Esistono due modi per modificare il valore di MutableLiveData. Ma qual è la differenza tra setValue()&postValue() in MutableLiveData.

Non sono riuscito a trovare la documentazione per lo stesso.

Ecco la classe MutableLiveDatadi 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);
    }
}

Risposte:


178

Sulla base della documentazione:

setValue () :

Imposta il valore. Se sono presenti osservatori attivi, il valore verrà inviato loro. Questo metodo deve essere chiamato dal thread principale.

postValue () :

Invia un'attività a un thread principale per impostare il valore specificato. Se hai chiamato questo metodo più volte prima che un thread principale eseguisse un'attività pubblicata, verrà inviato solo l'ultimo valore.

Per riassumere, la differenza fondamentale sarebbe:

setValue()metodo deve essere chiamato dal thread principale. Ma se hai bisogno di impostare un valore da un thread in background, postValue()dovrebbe essere usato.


"verrà inviato solo l'ultimo valore". Non posso esserne sicuro leggendo il codice. Quindi sembra che una volta che il primo thread sta per colpire il blocco sincronizzato interno all'interno di postValue (), la successiva finestra della CPU può essere potenzialmente data al thread 2 che sta inviando un altro valore. Il thread 2 può quindi completare il blocco sincronizzato e lo scheduler fornisce al primo thread una finestra per eseguire se stesso. Ora, sovrascrive ciò che il thread 2 ha già scritto. È possibile?
stdout

97

Tutte le risposte sopra sono corrette. Ma un'altra importante differenza. Se chiami postValue()su un campo che non ha osservatori e successivamente chiami getValue(), non ricevi il valore che hai impostato postValue(). Quindi fai attenzione se lavori in thread in background senza osservatori.


3
Vorrei poter triplicare il voto! Sulla base di ciò, sembra che sia meglio usare setValue()se possibile, e usare con cautela 'postValue ()', solo quando necessario. Grazie
jungledev

1
No, qui non c'è un modo "migliore". Se lavori con il tuo LiveData dal thread in background dovresti usare postValue. Anche nell'ultima versione dei componenti del ciclo di vita è stato risolto ... probabilmente.
w201

"Anche nell'ultima versione dei componenti del ciclo di vita è stato risolto ... probabilmente." Hai altre informazioni in merito? Grazie
Chris Nevill

1
Ho fatto alcuni test e sembra che con l'ultima versione di lib tutto funzioni come dovrebbe.
w201

Potresti mostrarmi concretamente il codice sopra? Se in ViewModel, ho implementato come noObserveLiveData.postValue("sample"), In Activity, quando ho usato getValue come viewModel.noObserveLiveData.getValueVuoi dire Non è il valore che ho impostato in postValue () ("sample")?
kwmt

14

setValue()viene chiamato direttamente dal thread del chiamante, notifica in modo sincrono agli osservatori e modifica LiveDataimmediatamente il valore. Può essere chiamato solo da MainThread.
postValue()usa qualcosa di simile all'interno new Handler(Looper.mainLooper()).post(() -> setValue()), quindi funziona setValuetramite HandlerMainThread. Può essere chiamato da qualsiasi thread.


11

setValue()

Imposta il valore. Se sono presenti osservatori attivi, il valore verrà inviato loro.

Questo metodo deve essere chiamato dal thread principale .

postValue

Se è necessario impostare un valore da un thread in background, è possibile utilizzare postValue(Object)

Invia un'attività a un thread principale per impostare il valore specificato.

Se hai chiamato questo metodo più volte prima che un thread principale eseguisse un'attività pubblicata, verrà inviato solo l'ultimo valore.


5

Questa non è una risposta diretta al problema di cui sopra. Le risposte di Sagar e w201 sono fantastiche. Ma una semplice regola pratica che uso in ViewModels per 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);
}

Sostituisci mutValcon il valore desiderato.


Bello, questo mi piace. In Kotlin ho creato un'estensione che incapsula l'aggiornamento intelligente in modo che i numerosi aggiornamenti dei valori in tutta la mia app siano una singola chiamata coerente.
Craig

4

setValue()metodo deve essere chiamato dal thread principale. Se è necessario impostare un valore da un thread in background, è possibile utilizzare postValue().

Altro qui .


0

Nella nostra app, abbiamo utilizzato un singolo LiveData che contiene dati per più visualizzazioni in un'attività / schermata. Fondamentalmente N no di set di dati per N no di visualizzazioni. Questo ci ha un po 'turbato perché il modo in cui postData è progettato. E abbiamo un oggetto di stato in LD che trasmette alla vista su quale vista deve essere aggiornata.

quindi LD ha questo aspetto:

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

Ci sono un paio di viste (view_1 e view_2) che dovevano essere aggiornate quando si verificava un evento. Significa che dovrebbero ricevere una notifica nello stesso momento in cui si verifica l'evento. Quindi, ho chiamato:

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

Questo non funzionerebbe per ragioni che sappiamo.

Quello che ho capito è che fondamentalmente un LD dovrebbe rappresentare solo una vista. Quindi non c'è alcuna possibilità che dovresti chiamare postData () due volte di seguito. Anche se chiami, il modo in cui postData lo gestisce per te è quello che ti aspetteresti anche tu (mostrandoti gli ultimi dati in vista). Tutto va a posto.

Un LD -> una vista. PERFETTO

Un LD -> più visualizzazioni POTREBBE ESSERE UN COMPORTAMENTO STRANO

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.