Neden ayrı bir MutableLiveData alt sınıfı LiveData var?


96

Görünüşe MutableLiveDatagöre, LiveDatayalnızca setValue()ve postValue()yöntemlerini halka açık hale getirmekten farklıdır , oysa LiveDatabunlar korunur.

Bu değişiklik için ayrı bir sınıf oluşturmanın ve bu yöntemleri LiveDatakendi içinde genel olarak tanımlamamanın bazı nedenleri nelerdir ?

Genel olarak, böyle bir kalıtım biçimi (tek değişiklik olarak belirli yöntemlerin görünürlüğünü arttırmak) iyi bilinen bir uygulama mıdır ve yararlı olabileceği bazı senaryolar nelerdir (tüm koda erişimimiz olduğunu varsayarak)?


10
bu bir tasarım kararıdır. LiveDatadeğiştirilemez, çünkü müşteri dahili durumu değiştiremez, bu nedenle iş parçacığı için güvenlidir
Blackbelt 18'17

Yanıtlar:


138

In LiveData - Android Geliştirici Belgeler , sizin için olduğunu görebilirsiniz LiveData, setValue()ve postValue()yöntemler herkese açık değildir.

Yılında ise MutableLiveData - Android Geliştirici Belgeleri , bunu görebiliyorum, MutableLiveDatauzanır LiveDataiçsel ve ayrıca iki sihirli yöntemler LiveDataise kamuya bu mevcut ve bunlar setValue()& postValue().

setValue(): değeri ayarlayın ve değeri tüm aktif gözlemcilere gönderin, ana iş parçacığından çağrılmalıdır .

postValue(): ayarlanan değeri geçersiz kılmak için ana iş parçacığına bir görev gönder setValue(), arka plan iş parçacığından çağrılmalıdır .

Yani, LiveDatabir değişmez . MutableLiveDataolduğu LiveDatahangi değişken & evreli .


36
LiveData gerçekten değişmez değildir, sadece ViewModel sınıfının dışında değiştirilemez . ViewModel sınıfı, onu istediği gibi değiştirebilir (örneğin, bir zamanlayıcı ViewModel). ViewModel sınıfının dışında değiştirmek isterseniz MutableLiveData'yı kullanırsınız.
Elliptica

2
Bu senaryoyu, Oda'nın gerçeğin Tek Kaynağı olduğu depo modeline (Sunucu + Oda) sahip bir uygulamayı ele alalım. Uygulama yalnızca Room'dan veri alırken, Room güncellemesini sunucudan alır. MutableLiveData, sunucu güncelleme Odası veya LiveData'dan gelen veriler kullanılabileceğinden kullanılması gerekir mi?
Dr4ke the b4dass

5
LiveData soyuttur, bu nedenle genişletmeden doğrudan LiveData nesnesi oluşturamazsınız. MutableLiveData, LiveData'yı genişletir.
Serdar Samancıoğlu

1
LiveData ve MutableLiveData için doğrudan kullanımdan kaldırılmış belgelere bağlantılar. Gerçek bağlantılar içeren bir düzenleme önerdiğimde neden reddedildi?
Daniel

1
@Daniel, inceleme sırasındaki diğer incelemeciler tarafından neden reddedildiğinden emin değil. Değişikliği onayladım, teşekkürler! :)
Sneh Pandya

10

Bu MutableLiveData.javadosyanın tamamı :

package androidx.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);
    }
}

Yani evet, fark sadece yaparak gelir postValueve setValuekamu.

Kafamdan hatırlayabildiğim bir kullanım durumu, Kotlin'de Backing Property kullanarak kapsülleme içindir . Sınıfınızda manipülasyona LiveDatasahip olsanız bile Parçanıza / Aktivitenize (UI Denetleyicisi) maruz kalabilirsiniz .MutableLiveDataViewModel

    class TempViewModel : ViewModel() {
        ...
        private val _count = MutableLiveData<Int>()
        val count: LiveData<Int>
            get() = _count
        public fun incrementCount() = _count.value?.plus(1)
        ...
    }

Bu şekilde, UI Denetleyiciniz değerleri düzenleyemeden yalnızca gözlemleyebilecektir. Açıkçası, UI Denetleyiciniz, TempViewModelbenzer yöntemleri kullanarak değerleri düzenleyebilir incrementCount().

Not : Değişken / değişmez kafa karışıklığını açıklığa kavuşturmak için -

data class User(var name: String, var age: Int)

class DemoLiveData: LiveData<User>()

var demoLiveData: LiveData<User>? = DemoLiveData()

fun main() {
    demoLiveData?.value = User("Name", 23) // ERROR
    demoLiveData?.value?.name = "Name" // NO ERROR
    demoLiveData?.value?.age = 23  // NO ERROR
}

Nedir _score?
IgorGanapolsky

0

MutableLiveData, LiveData'dan genişliyor. LiveData'nın korumalı yöntemleri yalnızca kendi kendine veya alt sınıflar tarafından ele alınabilir. Dolayısıyla, bu durumda MutableLiveData, LiveData'nın bir alt sınıfı olan bu korumalı yöntemlere erişebilir.

Yapmak istediğiniz şey, bir vakayı gözlemlemek ve herhangi bir değişiklik olup olmadığını görmek. Ama aynı zamanda, gözlemlemekte olduğunuz o örneği herhangi bir "yabancının" değiştirmesini istemezsiniz. Bir anlamda bu, bir nesneye sahip olmak, herhangi bir yeni durumu güncellemek ve değiştirilemez bir nesneye sahip olmak istediğinizden, bu örneği güncelleyemeyeceğinden emin olmak için bir sorun yaratır. Bu iki özellik birbiriyle çakışır ancak fazladan bir katman oluşturularak çözülebilir.

Yani yaptığınız şey, sınıfınızı, LiveData'yı, yöntemlerine erişebilen bir sınıfla genişletmektir. Alt katman, bu durumda MutableLiveData, ebeveyninin (/ super) korumalı yöntemlerine erişebilir.

Şimdi örnekler oluşturmaya başlarsınız ve MutableLiveData'nın gözlemci örneğini oluşturursunuz. Aynı zamanda aynı örneğe başvuran bir LiveData örneği oluşturursunuz. MutableLiveData, LiveData'yı genişlettiği için, herhangi bir MutableLiveData örneği bir LiveData nesnesidir ve bu nedenle bir LiveData değişkeni tarafından referans alınabilir.

Şimdi hile neredeyse bitti. Yalnızca LiveData örneğini açığa çıkarırsınız, hiç kimse korumalı yöntemlerini kullanamaz veya onu super değerine dönüştüremez (belki derleme zamanında, ancak çalışmaz: RunTime hatası). Ve gerçek alt sınıf örneğini özel tutarsınız, böylece yalnızca örneğin sahibi olanlar, örneğin yöntemlerini kullanarak değiştirilebilir.

//create instance of the sub class and keep this private
private val _name: MutableLiveData<String> = MutableLiveData<String>()
//create an instance of the super class referring to the same instance
val name: LiveData<String> = _name
//assign observer to the super class, being unable to change it
name.value.observe(.....)

Artık süper sınıf, herhangi bir değişiklik yapıldığında bildirimde bulunur.

//change the instance by using the sub class
_name.postValue(...)
//or _name.setValue(...)

Blok alıntı Genel olarak konuşursak, böyle bir kalıtım biçimi (tek değişiklik olarak belirli yöntemlerin görünürlüğünü arttırmak) iyi bilinen bir uygulama mıdır ve yararlı olabileceği bazı senaryolar nelerdir (tüm koda erişimimiz olduğunu varsayarsak)?

Evet, oldukça iyi bilinmektedir ve yukarıda açıklanan bu yaygın bir senaryodur. Gözlemci desenini kaldırın ve onu bir set / get formunda yapın, ondan en az o kadar fayda sağlayacaktır. Nerede uyguladığınıza bağlı olarak, sonunda altın kural yok.

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.