क्यों LiveData का एक अलग MutableLiveData उपवर्ग है?


96

यह केवल और तरीकों को सार्वजनिक करने MutableLiveDataसे अलग दिखता है , जबकि वे संरक्षित हैं।LiveDatasetValue()postValue()LiveData

इस बदलाव के लिए एक अलग वर्ग बनाने के कुछ कारण हैं और केवल उन तरीकों को सार्वजनिक रूप से परिभाषित नहीं करना LiveDataहै?

सामान्यतया, इस तरह की विरासत का एक रूप है (कुछ बदलावों की दृश्यता में वृद्धि केवल एक प्रसिद्ध अभ्यास है) एक प्रसिद्ध अभ्यास है और कुछ परिदृश्य क्या हैं जहां यह उपयोगी हो सकता है (यह मानते हुए कि हमारे पास सभी कोड तक पहुंच है)?


10
यह एक डिजाइन निर्णय है। LiveDataअपरिवर्तनीय है, क्योंकि ग्राहक आंतरिक स्थिति को बदल नहीं सकता है, इसलिए धागा-सुरक्षित
ब्लैकबेल्ट

जवाबों:


138

में LiveData - Android डेवलपर प्रलेखन , आप के लिए देख सकते हैं कि LiveData, setValue()और postValue()तरीकों को सार्वजनिक नहीं कर रहे हैं।

, जबकि में MutableLiveData - Android डेवलपर प्रलेखन , आप देख सकते हैं, MutableLiveDataफैली LiveDataकी आंतरिक और भी दो जादू तरीकों LiveDataहै सार्वजनिक रूप से इस में उपलब्ध है और वे कर रहे हैं setValue()और postValue()

setValue(): मान सेट करें और सभी सक्रिय पर्यवेक्षकों को मूल्य प्रेषित करें, मुख्य धागे से बुलाया जाना चाहिए ।

postValue(): कार्य को मुख्य थ्रेड पर सेट करें setValue(), जिसके द्वारा निर्धारित मान को ओवरराइड करें , बैकग्राउंड थ्रेड से बुलाया जाना चाहिए ।

तो, LiveDataहै अपरिवर्तनीयMutableLiveDataहै LiveDataजो परिवर्तनशील और धागे की सुरक्षित


37
यह वास्तव में नहीं है कि LiveData अपरिवर्तनीय है, बस यह कि ViewModel वर्ग के बाहर संशोधित नहीं किया जा सकता है । ViewModel वर्ग इसे संशोधित कर सकता है, हालांकि यह चाहता है (जैसे एक टाइमर ViewModel)। यदि आप इसे ViewModel वर्ग के बाहर संशोधित करना चाहते हैं, तो आप MutableLiveData का उपयोग करेंगे।
एलिप्टिका

2
आइए इस परिदृश्य को लेते हैं, रिपॉजिटरी पैटर्न (सर्वर + रूम) के साथ एक ऐप जहां कमरा सत्य का एकल स्रोत है। एप्लिकेशन को केवल कक्ष से डेटा मिलता है, जबकि कक्ष को सर्वर से अपडेट प्राप्त होता है। क्या mutableLiveData का उपयोग करना चाहिए क्योंकि सर्वर अपडेट कक्ष, या LiveData से डेटा का उपयोग किया जा सकता है?
b4dass

5
LiveData सार है, इसलिए आप इसका विस्तार किए बिना सीधे LiveData ऑब्जेक्ट नहीं बना सकते हैं। MutableLiveData LiveData का विस्तार करता है।
सेरदार समैंसिओलू

1
LiveData और MutableLiveData के लिंक सीधे वंचित प्रलेखन के लिए। जब मैंने वास्तविक लिंक के साथ एक संपादन का सुझाव दिया तो इसे अस्वीकार कर दिया गया था?
डेनिएल

1
@ डैनियल को यकीन नहीं था कि क्यों समीक्षा कतार में अन्य समीक्षकों द्वारा इसे अस्वीकार कर दिया गया था। मैंने बदलाव को मंजूरी दे दी है, धन्यवाद! :)
स्नेहा पंड्या

10

यह पूरी MutableLiveData.javaफाइल है:

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

तो हां, फर्क सिर्फ postValueऔर सिर्फ setValueसार्वजनिक करने से आता है ।

एक उपयोग मामला जिसे मैं अपने सिर से वापस बुला सकता हूं वह कोटलिन में बैकिंग प्रॉपर्टी का उपयोग करके एनकैप्सुलेशन के लिए है। आप अपनी कक्षा में हेरफेर के लिए LiveDataभले ही आप अपने फ्रैगमेंट / गतिविधि (यूआई नियंत्रक) को उजागर कर सकते हैं ।MutableLiveDataViewModel

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

इस तरह आपका UI नियंत्रक केवल उन्हें संपादित किए बिना ही मानों का पालन करने में सक्षम होगा। जाहिर है, आपके यूआई नियंत्रक TempViewModelजैसे सार्वजनिक तरीकों का उपयोग करके मूल्यों को संपादित कर सकते हैं incrementCount()

नोट : परस्पर / अपरिवर्तनीय भ्रम को स्पष्ट करने के लिए -

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
}

क्या है _score?
इगोरगानापोलस्की

0

MutableLiveData LiveData से विस्तारित हो रहा है। LiveData की संरक्षित विधियों को केवल स्वयं या उपवर्गों द्वारा संबोधित किया जा सकता है। तो इस मामले में MutableLiveData LiveData का एक उप वर्ग होने के नाते इन संरक्षित तरीकों तक पहुंच सकता है।

आप क्या करना चाहते हैं, एक उदाहरण पर गौर करें और देखें कि क्या कोई बदलाव हैं। लेकिन एक ही समय में आप नहीं चाहते हैं कि कोई भी "बाहरी व्यक्ति" उस उदाहरण को बदले जो आप देख रहे हैं। एक अर्थ में यह एक समस्या पैदा करता है, जैसा कि आप एक ऐसी वस्तु रखना चाहते हैं जो परिवर्तनशील हो, किसी भी नई स्थिति को अद्यतन करने के लिए, और परिवर्तनशील न हो, यह सुनिश्चित करने के लिए कि कोई भी इस उदाहरण को अद्यतन नहीं कर सकता है। ये दोनों एक-दूसरे के साथ संघर्ष करते हैं, लेकिन एक अतिरिक्त परत बनाकर हल किया जा सकता है।

तो आप जो भी करते हैं, अपनी कक्षा, LiveData को एक ऐसे वर्ग के साथ बढ़ाते हैं, जो अपने तरीकों तक पहुँच सकता है। उप परत, इस मामले में MutableLiveData, अपने माता-पिता (/ सुपर) के संरक्षित तरीकों का उपयोग करने में सक्षम है।

अब आप उदाहरण बनाना शुरू करते हैं, और MutableLiveData के अपने पर्यवेक्षक उदाहरण बनाते हैं। उसी समय आप इसी उदाहरण का जिक्र करते हुए LiveData उदाहरण बनाते हैं। क्योंकि MutableLiveData LiveData का विस्तार करता है, कोई भी MutableLiveData उदाहरण एक LiveData ऑब्जेक्ट है और इसलिए इसे LiveData चर द्वारा संदर्भित किया जा सकता है।

अब चाल लगभग पूरी हो चुकी है। आप केवल LiveData उदाहरण को उजागर करते हैं, कोई भी इसके संरक्षित तरीकों का उपयोग नहीं कर सकता है, और न ही इसे सुपर में डाल सकता है (शायद संकलन के समय, लेकिन यह रन नहीं होगा: रनटाइम त्रुटि)। और आप वास्तविक उप वर्ग उदाहरण को निजी रखते हैं, इसलिए यह केवल उन लोगों द्वारा बदला जा सकता है जो इंस्टेंस के तरीकों का उपयोग करते हैं।

//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(.....)

अब जब कोई परिवर्तन लागू किया जाता है तो सुपर क्लास सूचित करता है।

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

ब्लॉकचोट आम तौर पर बोलना, विरासत का एक ऐसा रूप है (केवल बदलाव के लिए कुछ तरीकों की दृश्यता में वृद्धि) एक प्रसिद्ध अभ्यास है और कुछ परिदृश्य क्या हैं जहां यह उपयोगी हो सकता है (यह मानते हुए कि हमारे पास सभी कोड तक पहुंच है)?

हां, यह काफी प्रसिद्ध है और ऊपर वर्णित यह एक सामान्य परिदृश्य है। ऑब्जर्वर पैटर्न को हटा दें, और इसे एक सेट में प्राप्त करें / फॉर्म प्राप्त करें इससे बस उतना ही लाभ होगा। जहां आप इसे लागू करते हैं, उस पर निर्भर करते हुए, अंत में कोई सुनहरा नियम नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.