MutableLiveData'da setValue () ve postValue () farkı


119

Değişim değerini yapmanın iki yolu vardır MutableLiveData. Ama setValue()ve postValue()arasındaki fark nedir MutableLiveData?

Aynı belgeyi bulamadım.

İşte MutableLiveDataAndroid sınıfı .

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

Yanıtlar:


198

Belgelere göre:

setValue () :

Değeri ayarlar. Aktif gözlemciler varsa, değer onlara gönderilecektir. Bu yöntem ana iş parçacığından çağrılmalıdır.

postValue () :

Verilen değeri ayarlamak için ana iş parçacığına bir görev gönderir. Bir ana iş parçacığı gönderilen bir görevi yürütmeden önce bu yöntemi birden çok kez çağırdıysanız, yalnızca son değer gönderilir.

Özetlemek gerekirse, temel fark şu şekilde olacaktır:

setValue()yöntem ana iş parçacığından çağrılmalıdır. Ancak bir arka plan iş parçacığından bir değer ayarlamanız gerekiyorsa, postValue()kullanılmalıdır.


"yalnızca son değer gönderilir". Kodu okuyarak bundan emin olamıyorum. Bu nedenle, ilk iş parçacığı postValue () içindeki eşzamanlı iç bloğa vurmak üzereymiş gibi görünüyor, bir sonraki CPU penceresi potansiyel olarak başka bir değer gönderen iş parçacığı 2'ye verilebilir. İş parçacığı 2 daha sonra senkronize edilmiş bloğu tamamlayabilir ve zamanlayıcı ilk iş parçacığına kendisini çalıştırması için bir pencere verir. Şimdi, iş parçacığı 2'nin zaten yazmış olduğu şeyin üzerine yazıyor. Mümkün mü?
stdout

109

Yukarıdaki cevapların tümü doğrudur. Ama bir önemli fark daha. postValue()Gözlemcisi olmayan bir sahayı ararsanız ve bundan sonra ararsanız getValue(), belirlediğiniz değeri almazsınız postValue(). Gözlemciler olmadan arka planda çalışıyorsanız dikkatli olun.


4
Keşke üç kat artırabilseydim! Buna dayanarak, setValue()mümkünse en iyisi ve yalnızca gerektiğinde 'postValue ()' kullanmak en iyisidir . Teşekkürler
jungledev

1
Hayır, "en iyi" yol burası değil. Arka plan iş parçacığından LiveData ile çalışıyorsanız, postValue kullanmanız gerekir. Ayrıca yaşam döngüsü bileşenlerinin en son sürümünde de düzeltildi ... muhtemelen.
w201

"Ayrıca yaşam döngüsü bileşenlerinin en son sürümünde de düzeltildi ... muhtemelen." Bununla ilgili daha fazla bilginiz var mı? Teşekkürler
Chris Nevill

1
Bazı testler yaptım ve lib'in son sürümüyle her şey olması gerektiği gibi çalışıyor gibi görünüyor.
w201

Yukarıdaki somut kodu bana gösterebilir misiniz? ViewModel'de noObserveLiveData.postValue("sample")getValue kullandığımda Aktivitede gibi viewModel.noObserveLiveData.getValueuyguladım Bunu mu demek istiyorsun postValue () ("sample") içinde belirlediğim değer değil mi?
kwmt

17

setValue()doğrudan arayan iş parçacığından çağrılır, eşzamanlı olarak gözlemcileri bilgilendirir ve LiveDatadeğeri anında değiştirir. Yalnızca MainThread'den çağrılabilir.
postValue()Böyle içinde bir şey kullanır new Handler(Looper.mainLooper()).post(() -> setValue())çalıştırır, böylece setValuearacılığıyla HandlerMainThread içinde. Herhangi bir ileti dizisinden çağrılabilir.


11

setValue()

Değeri ayarlar. Aktif gözlemciler varsa, değer onlara gönderilecektir.

Bu yöntem ana iş parçacığından çağrılmalıdır .

postValue

Arka plan iş parçacığından bir değer ayarlamanız gerekiyorsa, şunu kullanabilirsiniz: postValue(Object)

Verilen değeri ayarlamak için ana iş parçacığına bir görev gönderir.

Bir ana iş parçacığı gönderilen bir görevi yürütmeden önce bu yöntemi birden çok kez çağırdıysanız, yalnızca son değer gönderilir.


7

Bu, yukarıdaki soruna doğrudan bir cevap değildir. Sagar ve w201'in cevapları harika. Ancak ViewModels for MutableLiveData'da kullandığım basit bir kural şudur:

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

mutValİstediğiniz değerle değiştirin .


Güzel, bunu beğendim. Kotlin'de akıllı güncellemeyi kapsayan bir uzantı oluşturdum, böylece uygulamamdaki sayısız değer güncellemesi tek ve tutarlı bir çağrı.
19Craig

4

setValue()yöntem ana iş parçacığından çağrılmalıdır. Bir arka plan iş parçacığından bir değer ayarlamanız gerekiyorsa, kullanabilirsiniz postValue().

Daha fazlası burada .


0

Uygulamamızda, bir aktivite / ekranda birden çok görünüm için veri içeren tek LiveData kullandık. Temelde N görünüm sayısı için veri kümesi yok. Bu bizi biraz rahatsız etti çünkü postData için tasarlanma şekli. Ayrıca, LD'de hangi görünümün güncellenmesi gerektiği hakkında görüş bildiren durum nesnemiz var.

yani LD şuna benzer:

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

Bir olay meydana geldiğinde güncellenmesi gereken birkaç görünüm (görünüm_1 ve görünüm_2) vardır .. olay meydana geldiğinde aynı anda bilgilendirilmeleri gerektiği anlamına gelir. Ben de aradım:

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

Bu bildiğimiz nedenlerden dolayı işe yaramaz.

Anladığım şey, temelde bir LD'nin yalnızca bir görüşü temsil etmesi gerektiğidir. O zaman postData () 'yı art arda iki kez çağırmanız gerekmez. Arasanız bile, postData'nın sizin için işleyiş şekli de beklediğiniz şeydir (görünümde sizin için en son verileri gösterir). Her şey yerine oturuyor.

Bir LD -> bir Görünüm. MÜKEMMEL

Bir LD -> birden çok görünüm Tuhaf BİR DAVRANIŞ OLABİLİR

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.