MutableLiveData में setValue () और पोस्टवैल्यू () का अंतर


107

दो तरीके हैं जो परिवर्तन मूल्य बनाते हैं MutableLiveData। लेकिन मध्य क्या अंतर है setValue()और postValue()में MutableLiveData

मैं उसी के लिए दस्तावेज नहीं ढूंढ सका।

यहाँ 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);
    }
}

जवाबों:


179

प्रलेखन के आधार पर:

सेटवैल्यू () :

मान सेट करता है। यदि सक्रिय पर्यवेक्षक हैं, तो मूल्य उन्हें भेज दिया जाएगा। इस विधि को मुख्य धागे से बुलाया जाना चाहिए।

पोस्टवैल्यू () :

दिए गए मान को सेट करने के लिए एक मुख्य सूत्र के लिए एक कार्य पोस्ट करता है। यदि आप किसी पोस्ट किए गए कार्य को निष्पादित करने से पहले कई बार इस विधि को कहते हैं, तो केवल अंतिम मान भेजा जाएगा।

संक्षेप में, मुख्य अंतर यह होगा:

setValue()विधि को मुख्य धागे से बुलाया जाना चाहिए। लेकिन अगर आपको पृष्ठभूमि थ्रेड से मान सेट करने की आवश्यकता है, postValue()तो इसका उपयोग किया जाना चाहिए।


"केवल अंतिम मान भेजा जाएगा"। मैं कोड पढ़कर इसके बारे में निश्चित नहीं हो सकता। तो ऐसा लगता है कि एक बार जब पहला धागा पोस्टवैल्यू () के अंदर इनर सिंक्रोनाइज्ड ब्लॉक को हिट करने के बारे में हो जाता है, तो अगली सीपीयू विंडो को संभावित रूप से थ्रेड 2 को दिया जा सकता है जो दूसरे मूल्य पर पोस्ट कर रहा है। थ्रेड 2 तब सिंक्रनाइज़ किए गए ब्लॉक को पूरा कर सकता है और अनुसूचक पहले थ्रेड को स्वयं चलाने के लिए एक विंडो देता है। अब, यह ओवरराइट करता है जो थ्रेड 2 पहले ही लिख चुका है। क्या यह संभव है?
stdout

98

उपरोक्त सभी उत्तर सही हैं। लेकिन एक और महत्वपूर्ण अंतर। यदि आप postValue()उस फ़ील्ड पर कॉल करते हैं जिसका कोई पर्यवेक्षक नहीं है और उसके बाद आप कॉल करते हैं getValue(), तो आपको वह मान प्राप्त नहीं होता है जिसे आप सेट करते हैं postValue()। तो सावधान रहें यदि आप पर्यवेक्षकों के बिना पृष्ठभूमि के धागे में काम करते हैं।


3
काश मैं ट्रिपल-अपवोट कर पाता! इसके आधार पर, setValue()यदि संभव हो तो इसका उपयोग करना सबसे अच्छा प्रतीत होता है, और आवश्यक होने पर ही सावधानीपूर्वक 'पोस्टवैल्यू ()' का उपयोग करें। धन्यवाद
jungledev

1
नहीं, यहाँ कोई "सर्वश्रेष्ठ" तरीका नहीं है। यदि आप बैकग्राउंड थ्रेड से अपने LiveData के साथ काम करते हैं तो आपको पोस्टवैल्यू का उपयोग करना चाहिए। इसके अलावा जीवन चक्र घटकों के नवीनतम संस्करण में यह तय ... शायद।
w201

"इसके अलावा जीवन चक्र घटकों के नवीनतम संस्करण में यह तय ... शायद।" क्या आपके पास इस पर कोई और जानकारी है? धन्यवाद
क्रिस Nevill

1
मैंने कुछ परीक्षण किए और लगता है कि पिछले संस्करण के साथ सब कुछ ठीक उसी तरह काम करता है जैसा कि इसे करना चाहिए।
w201

क्या आप मुझे उपर्युक्त कोड दिखा सकते हैं? अगर ViewModel में, मैंने कार्यान्वित किया noObserveLiveData.postValue("sample"), जैसे कि , गतिविधि में, जब मैंने viewModel.noObserveLiveData.getValuegetValue का उपयोग किया, तो क्या आपका मतलब यह है कि क्या मैं पोस्टवैल्यू () ("नमूना") में निर्धारित मूल्य नहीं है?
kwmt

14

setValue()कॉलर थ्रेड से सीधे कहा जाता है, तुल्यकालिक रूप से पर्यवेक्षकों को सूचित करता है और LiveDataतुरंत मूल्य बदलता है । इसे केवल MainThread से कहा जा सकता है।
postValue()इस तरह के अंदर कुछ का उपयोग करता है new Handler(Looper.mainLooper()).post(() -> setValue())तो यह चलता है, setValueके माध्यम से HandlerMainThread में। इसे किसी भी धागे से बुलाया जा सकता है।


11

setValue()

मान सेट करता है। यदि सक्रिय पर्यवेक्षक हैं, तो मूल्य उन्हें भेज दिया जाएगा।

इस विधि को मुख्य धागे से बुलाया जाना चाहिए

postValue

यदि आपको पृष्ठभूमि थ्रेड से मान सेट करने की आवश्यकता है, तो आप उपयोग कर सकते हैं postValue(Object)

दिए गए मान को सेट करने के लिए एक मुख्य सूत्र के लिए एक कार्य पोस्ट करता है।

यदि आप किसी पोस्ट किए गए कार्य को निष्पादित करने से पहले कई बार इस विधि को कहते हैं, तो केवल अंतिम मान भेजा जाएगा।


5

यह उपरोक्त समस्या का सीधा जवाब नहीं है। सागर और w201 के जवाब कमाल के हैं। लेकिन MutableLiveData के लिए ViewModels में अंगूठे का उपयोग करने का एक सरल नियम है:

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अपने वांछित मूल्य के साथ बदलें ।


अच्छा लगा, मुझे यह पसंद है। Kotlin में मैंने एक एक्सटेंशन बनाया जो स्मार्ट अपडेट को इनकैप्सुलेट करता है इसलिए मेरे ऐप में कई वैल्यू अपडेट एक सिंगल, सुसंगत कॉल हैं।
क्रेग

4

setValue()विधि को मुख्य धागे से बुलाया जाना चाहिए। यदि आपको पृष्ठभूमि थ्रेड से मान सेट करने की आवश्यकता है, तो आप उपयोग कर सकते हैं postValue()

अधिक यहाँ


0

हमारे ऐप में, हमने एकल LiveData का उपयोग किया है जिसमें एक गतिविधि / स्क्रीन में कई दृश्यों के लिए डेटा है। मूल रूप से N नहीं दृश्यों के लिए कोई डेटासेट नहीं है। यह हमें थोड़ा परेशान करता है क्योंकि जिस तरह से पोस्टडेटा के लिए डिज़ाइन किया गया है। और एलडी में हमारे पास राज्य वस्तु है जो यह देखने के लिए बताती है कि किस दृश्य को अपडेट करने की आवश्यकता है।

तो एलडी इस तरह दिखता है:

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

कुछ दृश्य हैं (view_1 और view_2) जिन्हें किसी एक घटना के होने पर अद्यतन किया जाना था..जबकि उन्हें उसी समय सूचित किया जाना चाहिए जब घटना होती है। तो, मैंने फोन किया:

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

यह उन कारणों के लिए काम नहीं करेगा जिन्हें हम जानते हैं।

मैंने जो समझा वह यह है कि मूल रूप से एक एलडी को केवल एक दृश्य का प्रतिनिधित्व करना चाहिए। फिर कोई मौका नहीं है कि आपको पंक्ति में दो बार पोस्टडेटा () कॉल करना होगा। यहां तक ​​कि अगर आप कॉल करते हैं, तो जिस तरह से पोस्टडेटा आपके लिए इसे संभालता है, वह वह है जो आप भी उम्मीद करेंगे (आपके लिए नवीनतम डेटा को ध्यान में रखते हुए)। सबकुछ जगह-जगह गिर जाता है।

एक एलडी -> एक दृश्य। उत्तम

एक LD -> कई विचार एक दिन पहले हो जाएगा

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