Perbedaan setValue () & postValue () di MutableLiveData

107

Ada dua cara yang membuat nilai perubahan MutableLiveData. Tapi apa perbedaan antara setValue()& postValue()in MutableLiveData.

Saya tidak dapat menemukan dokumentasi yang sama.

Ini dia kelas MutableLiveDataAndroid.

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);
    }
}
Khemraj
sumber

Jawaban:

179

Berdasarkan dokumentasi:

setValue () :

Tetapkan nilainya. Jika ada pengamat yang aktif, nilainya akan dikirimkan kepada mereka. Metode ini harus dipanggil dari utas utama.

postValue () :

Posting tugas ke utas utama untuk menyetel nilai yang diberikan. Jika Anda memanggil metode ini beberapa kali sebelum thread utama mengeksekusi tugas yang diposting, hanya nilai terakhir yang akan dikirim.

Untuk meringkas, perbedaan utamanya adalah:

setValue()metode harus dipanggil dari utas utama. Tetapi jika Anda perlu mengatur nilai dari thread latar belakang, postValue()harus digunakan.

Sagar
sumber
"hanya nilai terakhir yang akan dikirim". Saya tidak bisa memastikannya dengan membaca kodenya. Jadi sepertinya begitu utas pertama akan mencapai blok sinkron dalam di dalam postValue (), jendela CPU berikutnya dapat berpotensi diberikan ke utas 2 yang memposting nilai lain. Utas 2 kemudian dapat menyelesaikan blok yang disinkronkan dan penjadwal memberikan utas pertama jendela untuk berjalan sendiri. Sekarang, itu menimpa apa yang telah ditulis utas 2. Apakah ini mungkin?
stdout
98

Semua jawaban di atas benar. Tapi satu perbedaan penting lagi. Jika Anda memanggil postValue()di lapangan yang tidak memiliki pengamat dan setelah itu Anda memanggil getValue(), Anda tidak menerima nilai yang Anda tetapkan postValue(). Jadi berhati-hatilah jika Anda bekerja di thread latar belakang tanpa pengamat.

w201
sumber
3
Seandainya saya bisa mendapatkan suara positif tiga kali lipat! Berdasarkan hal ini, tampaknya yang terbaik adalah menggunakan setValue()jika memungkinkan, dan hati-hati gunakan 'postValue ()', hanya jika diperlukan. Terima kasih
jungledev
1
Tidak, di sini tidak ada cara "terbaik". Jika Anda bekerja dengan LiveData dari utas latar belakang, Anda harus menggunakan postValue. Juga dalam versi terbaru dari komponen siklus hidup itu diperbaiki ... mungkin.
w201
"Juga dalam versi terbaru dari komponen siklus hidup, ini diperbaiki ... mungkin." Apakah Anda memiliki informasi lebih lanjut tentang ini? Terima kasih
Chris Nevill
1
Saya melakukan beberapa tes dan tampaknya dengan versi terakhir lib semuanya berfungsi sebagaimana mestinya.
w201
Bisakah Anda menunjukkan kepada saya kode konkret di atas? Jika Dalam ViewModel, Saya Menerapkan seperti noObserveLiveData.postValue("sample"), Dalam Aktivitas, ketika saya menggunakan getValue seperti viewModel.noObserveLiveData.getValueMaksud Anda Bukankah itu nilai yang saya tetapkan di postValue () ("sample")?
kwmt
14

setValue()dipanggil langsung dari utas pemanggil, secara sinkron memberi tahu pengamat dan mengubah LiveDatanilai dengan segera. Ini hanya dapat dipanggil dari MainThread.
postValue()digunakan di dalam sesuatu seperti ini new Handler(Looper.mainLooper()).post(() -> setValue()), sehingga berjalan setValuemelalui Handlerdi MainThread. Itu dapat dipanggil dari utas apa pun.

Ufkoku
sumber
11

setValue()

Tetapkan nilainya. Jika ada pengamat yang aktif, nilainya akan dikirimkan kepada mereka.

Metode ini harus dipanggil dari utas utama .

postValue

Jika Anda perlu menyetel nilai dari thread latar belakang, Anda dapat menggunakan postValue(Object)

Posting tugas ke utas utama untuk menyetel nilai yang diberikan.

Jika Anda memanggil metode ini beberapa kali sebelum thread utama mengeksekusi tugas yang diposting, hanya nilai terakhir yang akan dikirim.

Nilesh Rathod
sumber
5

Ini bukanlah jawaban langsung untuk masalah di atas. Jawaban dari Sagar dan w201 luar biasa. Tapi aturan praktis sederhana yang saya gunakan di ViewModels untuk MutableLiveData adalah:

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);
}

Gantilah mutValdengan nilai yang Anda inginkan.

Himujjal Upadhyaya
sumber
Bagus, saya suka ini. Di Kotlin saya membuat ekstensi yang merangkum pembaruan pintar sehingga banyak pembaruan nilai di seluruh aplikasi saya adalah panggilan tunggal yang konsisten.
19Craig
4

setValue()metode harus dipanggil dari utas utama. Jika Anda perlu menyetel nilai dari thread latar belakang, Anda dapat menggunakan postValue().

Lebih lanjut di sini .

Levon Petrosyan
sumber
0

Di aplikasi kami, kami telah menggunakan LiveData tunggal yang berisi data untuk beberapa tampilan di aktivitas / layar. Pada dasarnya N tidak ada dataset untuk N tidak ada view. Ini sedikit mengganggu kami karena cara postData dirancang. Dan kami memiliki objek status di LD yang menyampaikan untuk melihat tentang tampilan mana yang perlu diperbarui.

jadi LD terlihat seperti ini:

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

Ada beberapa tampilan (view_1 dan view_2) yang harus diupdate saat satu peristiwa terjadi..berarti tampilan tersebut harus mendapat pemberitahuan pada saat yang sama saat peristiwa terjadi. Jadi, saya menelepon:

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

Ini tidak akan berhasil karena alasan yang kita tahu.

Apa yang saya pahami adalah pada dasarnya satu LD seharusnya hanya mewakili satu pandangan. Maka tidak ada kemungkinan Anda harus memanggil postData () dua kali berturut-turut. Bahkan jika Anda memanggil, cara postData menanganinya untuk Anda adalah apa yang juga Anda harapkan (menampilkan data terbaru untuk Anda dalam tampilan). Semuanya berjalan dengan baik pada tempatnya.

Satu LD -> satu Tampilan. SEMPURNA

Satu LD -> beberapa tampilan MUNGKIN ADA PERILAKU YANG ANEH

cgr
sumber