ViewModel से LiveData का अवलोकन करना


96

मेरे पास एक अलग वर्ग है जिसमें मैं डेटा फ़ेचिंग (विशेष रूप से फायरबेस) संभालता हूं और मैं आमतौर पर लाइवडैट ऑब्जेक्ट्स को इससे वापस करता हूं और उन्हें अतुल्यकालिक रूप से अपडेट करता हूं। अब मैं एक ViewModel में संग्रहीत डेटा लौटा देना चाहता हूं, लेकिन समस्या यह है कि उक्त मूल्य प्राप्त करने के लिए, मुझे अपने डेटा लाने वाले वर्ग से लौटे LiveData ऑब्जेक्ट का निरीक्षण करना होगा। अवलोकन विधि के लिए पहले पैरामीटर के रूप में एक LifecycleOwner ऑब्जेक्ट की आवश्यकता होती है, लेकिन मुझे स्पष्ट रूप से मेरे ViewModel के अंदर ऐसा नहीं है और मुझे पता है कि मैं ViewModel के अंदर गतिविधि / फ़्रैगमेंट का संदर्भ नहीं रखने वाला हूं। मुझे क्या करना चाहिए?


जवाबों:


39

में इस ब्लॉग पोस्ट गूगल डेवलपर जोस Alcérreca द्वारा यह इस मामले में एक परिवर्तन का उपयोग करने के ( "खजाने में LiveData" पैरा देखें) क्योंकि सिफारिश की है ViewModel से संबंधित किसी भी संदर्भ पकड़ नहीं करना चाहिए View(गतिविधि, प्रसंग आदि) क्योंकि यह मुश्किल बना दिया मापना।


क्या आप अपने लिए परिवर्तनकारी कार्य प्राप्त करने में सफल रहे हैं? मेरी घटनाएँ काम नहीं कर रही हैं
रोमेनसो

27
अपने आप पर रूपांतरण काम नहीं करते हैं, क्योंकि आप जिस भी कोड को ट्रांसफॉर्मेशन में लिखते हैं वह केवल चलाने के लिए जुड़ा होता है जब कोई इकाई परिवर्तन देखती है
परिक्रमा

9
मुझे नहीं पता कि यह अनुशंसित उत्तर क्यों है, इसका सवाल से कोई लेना-देना नहीं है। 2 साल बाद, और हम अभी भी नहीं जानते हैं कि हमारे व्यूमोडल में रिपॉजिटरी डेटा परिवर्तनों का निरीक्षण कैसे करें।
एंड्रयू

27

में ViewModel प्रलेखन

हालाँकि, ViewModel ऑब्जेक्ट्स को कभी भी जीवनचक्र के प्रति सजग वेधशालाओं जैसे कि LiveData ऑब्जेक्ट्स में परिवर्तन नहीं देखना चाहिए।

डेटा के लिए एक और तरीका है LiveData के बजाय RxJava को लागू करना, फिर उसे जीवनचक्र के प्रति जागरूक होने का लाभ नहीं होगा।

Todo-mvvm-live-kotlin के Google नमूने में , यह ViewModel में LiveData के बिना कॉलबैक का उपयोग करता है।

मैं अनुमान लगा रहा हूं कि क्या आप जीवनचक्र-वेयर होने के पूरे विचार का पालन करना चाहते हैं, हमें गतिविधि / फ़्रिबरमेंट में अवलोकन कोड को स्थानांतरित करने की आवश्यकता है। और, हम ViewModel में कॉलबैक या RxJava का उपयोग कर सकते हैं।

एक और समझौता MediatorLiveData (या ट्रांसफॉर्मेशन) को लागू करने और ViewModel में अपना तर्क (यहां अपना तर्क रखने) का पालन करें। ध्यान दें कि MediatorLiveData ऑब्जर्वर तब तक ट्रिगर नहीं होगा (जब तक कि यह ट्रांसफॉर्मेशन न हो) जब तक यह एक्टिविटी / फ्रैगमेंट में नहीं दिखता है। हम जो कुछ भी करते हैं वह गतिविधि / फ्रैगमेंट में एक खाली अवलोकन है, जहां वास्तविक कार्य वास्तव में ViewModel में किया जाता है।

// ViewModel
fun start(id : Long) : LiveData<User>? {
    val liveData = MediatorLiveData<User>()
    liveData.addSource(dataSource.getById(id), Observer {
        if (it != null) {
            // put your logic here
        }
    })
}

// Activity/Fragment
viewModel.start(id)?.observe(this, Observer {
    // blank observe here
})

PS: मैंने ViewModels और LiveData: पैटर्न्स + एंटीपैटर्नस को पढ़ा जो सुझाव दिया कि ट्रांसफॉर्मेशन। मुझे नहीं लगता कि यह तब तक काम करता है जब तक कि LiveData का अवलोकन नहीं किया जाता है (जिसे संभवतः गतिविधि / परिमार्जन में किया जाना चाहिए)।


2
क्या इस संबंध में कुछ बदला? या RX, कॉलबैक या रिक्त निरीक्षण केवल समाधान हैं?
qbait

2
इन खाली टिप्पणियों से छुटकारा पाने का कोई उपाय?
एहसान मशहदी

1
शायद प्रवाह ( mLiveData.asFlow()) या का उपयोग कर observeForever
मचाडो

फ्लो सॉल्यूशन काम करने लगता है यदि आप नहीं चाहते हैं / आपको Fragment में किसी पर्यवेक्षक तर्क की आवश्यकता नहीं है
adek111

14

मुझे लगता है कि आप अवलोकन का उपयोग कर सकते हैं, जिसे जीवनचक्र के स्वामी इंटरफ़ेस की आवश्यकता नहीं है और आप व्यूमोडेल से परिणाम देख सकते हैं


2
यह मेरे लिए विशेष रूप से सही उत्तर है कि ViewModel.onCleared () के बारे में डॉक्स में कहा गया है: "यह तब उपयोगी होता है जब ViewModel कुछ डेटा का अवलोकन करता है और आपको इस ViewModel के रिसाव को रोकने के लिए इस सदस्यता को साफ़ करने की आवश्यकता होती है।"
योसेफ

2
क्षमा करें लेकिनCannot invoke observeForever on a background thread
बोकेन

1
जो काफी जायज लगता है। हालांकि एक को देखने के क्षेत्र में पर्यवेक्षकों को बचाने के लिए और पर सदस्यता समाप्त करना है onCleared। पृष्ठभूमि धागे के रूप में - मुख्य धागे से निरीक्षण करें, बस।
किरिल स्ट्रॉस्टिन

@ बोकेन आपको observeForeverमुख्य के माध्यम से आमंत्रित किया जा सकता हैGlobalScope.launch(Dispatchers.Main) { myvm.observeForever() }
rmirabelle

5

आर्किटेक्चर घटकों के साथ कोटलिन कॉटआउट का उपयोग करें।

आप liveDataफ़ंक्शन को कॉल करने के लिए बिल्डर फ़ंक्शन का उपयोग कर सकते हैं suspend, परिणाम को LiveDataऑब्जेक्ट के रूप में प्रस्तुत कर सकते हैं ।

val user: LiveData<User> = liveData {
    val data = database.loadUser() // loadUser is a suspend function.
    emit(data)
}

आप ब्लॉक से कई मान भी निकाल सकते हैं। प्रत्येक emit()कॉल ब्लॉक के निष्पादन को निलंबित करता है जब तक LiveDataकि मुख्य धागे पर मूल्य सेट नहीं किया जाता है।

val user: LiveData<Result> = liveData {
    emit(Result.loading())
    try {
        emit(Result.success(fetchUser()))
    } catch(ioException: Exception) {
        emit(Result.error(ioException))
    }
}

अपने श्रेणी विन्यास में, का उपयोग करें androidx.lifecycle:lifecycle-livedata-ktx:2.2.0 या उच्चतर।

वहाँ भी एक है इसके बारे में लेख है।

अपडेट : इसके अलावा इसे बदलने के लिए संभव है LiveData<YourData>में Dao interface। आपको suspendफ़ंक्शन में कीवर्ड जोड़ने की आवश्यकता है :

@Query("SELECT * FROM the_table")
suspend fun getAll(): List<YourData>

और ViewModelआपको इसे इस तरह से समरूप रूप से प्राप्त करने की आवश्यकता है:

viewModelScope.launch(Dispatchers.IO) {
    allData = dao.getAll()
    // It's also possible to sync other data here
}

0

मुझे पता है कि इस विषय के लिए पहले से ही अद्भुत जवाब हैं, लेकिन मैं अपना खुद का भी जोड़ना चाहता था:

आप रहना चाहते हैं LiveDataतो आप हमेशा उपयोग कर सकते हैं Transformations.mapताकि आप की जरूरत नहीं है कि observeमें ViewModelबल्कि केवल में Fragment/ Activity

अन्यथा, आप उपयोग कर सकते हैं SharedFlow, एक भी घटना देखने योग्य है। अधिक जानकारी के लिए, मैंने यहां एक लेख लिखा है: https://coroutinedispatcher.com/posts/decorate_stateful_mvvm/

उत्तीर्ण होने के लिए की जरूरत नहीं है viewLifecycleOwnerमें ViewModelक्योंकि बुला का कोई मतलब नहीं है वहाँ observeमें ViewModelजब Viewबस सब के बाद नवीनतम परिणाम की जरूरत है।


0

प्रवाह का उपयोग करें

डॉक्स में दिशानिर्देश गलत समझा गया है

हालाँकि, ViewModel ऑब्जेक्ट्स को कभी भी जीवनचक्र के प्रति सजग वेधशालाओं जैसे कि LiveData ऑब्जेक्ट्स में परिवर्तन नहीं देखना चाहिए।

इस गितुब मुद्दे में , वह वर्णन करता है कि उपरोक्त नियम लागू किए जाने वाले हालात हैं कि देखे गए जीवनचक्र के प्रति सजग वेधशालाओं को एक अन्य जीवनचक्र दायरे द्वारा होस्ट किया जाता है। कोई समस्या नहीं है कि का अवलोकन करता है LiveDataमें ViewModelमनाया शामिल LiveData

प्रवाह का उपयोग करें

class MyViewModel : ViewModel() {
    private val myLiveData = MutableLiveData(1)

    init {
        viewModelScope.launch {
            myLiveData.asFlow().collect {
                // Do Something
            }
        }
    }
}

StateFlow का उपयोग करें

class MyViewModel : ViewModel() {
    private val myFlow = MutableStateFlow(1)
    private val myLiveData = myFlow.asLiveData(viewModelScope.coroutineContext)
}

पी.एस.

asFlowएक प्रवाह है कि बनाता है बनाता है LiveDataशुरू करने पर सक्रिय करें collect। मुझे लगता है कि डमी ऑब्जर्वर के साथ MediatorLiveDataया Transformationsसंलग्न करने के समाधान में अंतर का उपयोग करने के Flowअलावा कोई अंतर नहीं है , LiveDataजो हमेशा ViewModelउदाहरण में देखा जाता है ।

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