कोटलिन फ्लो बनाम Android LiveData


20

कोटलिन फ्लो के बारे में मेरे कुछ सवाल हैं

  1. मैं कई अंशों से LiveData का निरीक्षण कर सकता हूं। क्या मैं फ्लो के साथ ऐसा कर सकता हूं? यदि हाँ तो कैसे?
  2. हम का उपयोग कर एक भी LiveData से कई LiveData हो सकता है mapऔर switchMap। क्या किसी एकल स्रोत प्रवाह से कई प्रवाह होने का कोई तरीका है?
  3. उपयोग करने से MutableLiveDataमैं चर संदर्भ का उपयोग करके कहीं से भी डेटा अपडेट कर सकता हूं। क्या फ्लो के साथ भी ऐसा करने का कोई तरीका है?

मेरे पास एक उपयोग-मामला है: मैं एक SharedPreferencesप्रयोग का निरीक्षण callbackFlow{...}करूंगा जो मुझे एकल स्रोत प्रवाह देगा। उस फ़्लो से, मैं प्रत्येक की-वैल्यू पेयर के लिए मल्टीपल फ़्लो बनाना चाहता हूँ।

ये मूर्खतापूर्ण सवाल लग सकता है। मैं आरएक्स और फ्लो की दुनिया में नया हूं।


आपने किस दृष्टिकोण पर समझौता किया - फ्लो या लाइवडेटा ?
इगोरगानापोलस्की

2
वर्तमान में, मैं LiveData का उपयोग अन्य लोगों के विचारों और प्रवाह के लिए कर रहा हूं। ViewModel में, मुझे फ़्लो प्राप्त होता है और टुकड़ों से अवलोकन करने के लिए LiveData का उत्सर्जन करता है।
zoha131

@ zoha131 आप इसे सही तरीके से करते हैं! चूंकि LiveData को केवल मुख्य धागे पर ही देखा जा सकता है, वे देखने के लिए पूरी तरह से फिट होते हैं <-> ViewModel इंटरैक्शन। फिर फ्लो आपको अपने बाकी आर्किटेक्चर में अधिक जटिल ऑपरेशन करने देता है।
स्मोरा

जवाबों:


15

मैं कई अंशों से LiveData का निरीक्षण कर सकता हूं। क्या मैं फ्लो के साथ ऐसा कर सकता हूं? यदि हाँ तो कैसे?

हाँ। आप इसके साथ emitऔर कर सकते हैं collect। सोचना emitलाइव डेटा के समान है postValueऔर collectइसके समान है observe। एक उदाहरण देते हैं।

कोष

// I just faked the weather forecast
val weatherForecast = listOf("10", "12", "9")

// This function returns flow of forecast data
// Whenever the data is fetched, it is emitted so that
// collector can collect (if there is any)
fun getWeatherForecastEveryTwoSeconds(): Flow<String> = flow { 
    for (i in weatherForecast) {
        delay(2000)
        emit(i)
    }
}

ViewModel

fun getWeatherForecast(): Flow<String> {
    return forecastRepository.getWeatherForecastEveryTwoSeconds()
}

टुकड़ा

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    // Collect is suspend function. So you have to call it from a 
    // coroutine scope. You can create a new coroutine or just use 
    // lifecycleScope
    // https://developer.android.com/topic/libraries/architecture/coroutines
    lifecycleScope.launch {
            viewModel.getWeatherForecastEveryTwoSeconds().collect {
                    // Use the weather forecast data
                    // This will be called 3 times since we have 3 
                    // weather forecast data
            }
    }
}

हम नक्शे और स्विचपाइप का उपयोग करके एक एकल LiveData से कई LiveData कर सकते हैं। क्या किसी एकल स्रोत प्रवाह से कई प्रवाह होने का कोई तरीका है?

प्रवाह बहुत आसान है। आप केवल प्रवाह के अंदर प्रवाह बना सकते हैं। कहते हैं कि आप प्रत्येक मौसम पूर्वानुमान डेटा में डिग्री साइन अप करना चाहते हैं।

ViewModel

fun getWeatherForecast(): Flow<String> {
    return flow {
        forecastRepository
            .getWeatherForecastEveryTwoSeconds(spendingDetailsRequest)
                .map {
                    it + " °C"
                }
                .collect {
                    // This will send "10 °C", "12 °C" and "9 °C" respectively
                    emit(it) 
                }
    }
}

फिर # 1 के समान ही Fragment में डेटा एकत्र करें। यहाँ क्या होता है व्यू मॉडल रिपॉजिटरी से डेटा इकट्ठा कर रहा है और टुकड़ा व्यू मॉडल से डेटा इकट्ठा कर रहा है।

MutableLiveData का उपयोग करके मैं चर संदर्भ का उपयोग करके कहीं से भी डेटा अपडेट कर सकता हूं। क्या फ्लो के साथ भी ऐसा करने का कोई तरीका है?

आप प्रवाह के बाहर मूल्य फेंक सकते हैं। किसी भी कलेक्टर के होने पर प्रवाह के अंदर कोड ब्लॉक को निष्पादित किया जाता है। लेकिन आप LiveData से asLiveData एक्सटेंशन का उपयोग करके प्रवाह को लाइव डेटा में बदल सकते हैं।

ViewModel

fun getWeatherForecast(): LiveData<String> {
    return forecastRepository
    .getWeatherForecastEveryTwoSeconds()
    .asLiveData() // Convert flow to live data
}

आपके मामले में आप ऐसा कर सकते हैं

private fun getSharedPrefFlow() = callbackFlow {
    val sharedPref = context?.getSharedPreferences("SHARED_PREF_NAME", MODE_PRIVATE)
    sharedPref?.all?.forEach {
        offer(it)
    }
}

getSharedPrefFlow().collect {
    val key = it.key
    val value = it.value
}

संपादित करें

उनकी टिप्पणी के लिए @mark का धन्यवाद। getWeatherForecastफ़ंक्शन के लिए दृश्य मॉडल में एक नया प्रवाह बनाना वास्तव में अनावश्यक है। इसे फिर से लिखा जा सकता है

fun getWeatherForecast(): Flow<String> {
        return forecastRepository
                .getWeatherForecastEveryTwoSeconds(spendingDetailsRequest)
                    .map {
                        it + " °C"
                    }
    }

मुझे पता नहीं क्यों, लेकिन मुझे एक धारणा थी कि मैं एक प्रवाह के लिए कई स्थानों पर संग्रह () फ़ंक्शन को कॉल नहीं कर सकता। जवाब के लिए धन्यवाद।
zoha131

1
नहीं। आप एक ही प्रवाह को कई स्थानों पर एकत्र कर सकते हैं। val sharedPref = getSharedPref()और आप कई स्थानों पर एकत्रित का उपयोग कर सकते हैं sharedPref.collect {}। केवल एक चीज क्योंकि संग्रह निलंबित है, आपको इसे कोरटाइन ब्लॉक से कॉल करने की आवश्यकता है। और एनपी की मदद करने के लिए खुश :)
फतह

मेरे तीसरे प्रश्न के लिए, वर्कअराउंड प्रसारण चैनल हो सकता है।
zoha131

आप लाइव डेटा के बजाय चैनलों का उपयोग करने के लिए इस प्रतिबद्ध की जांच कर सकते हैं। github.com/android/plaid/pull/770/commits/…
Fatih

1
हाँ आप सही है। यह वह जगह है जहां प्रवाह आता है। चैनल में बहुत सी चीजें हैं जिन्हें आपको ध्यान रखना है और वे गर्म अर्थ हैं कि वे हमेशा खुले रहते हैं भले ही कोई पर्यवेक्षक न हो। लेकिन प्रवाह के साथ आप बिना किसी चिंता के समान लाभ प्राप्त कर सकते हैं क्योंकि वे ठंडे हैं। इसलिए चैनल के बजाय मुझे लगता है कि प्रवाह का उपयोग करना बेहतर है
फतह

3

Flow.asLiveData()नए androidx.lifecyclektx पैकेज में एक नया एक्सटेंशन फ़ंक्शन है। आप मेरे लेख में अधिक जान सकते हैं: https://www.netguru.com/codestories/android-coroutines-%EF%B8%8Fin-2020


हमें इसका उपयोग कब करने की आवश्यकता है?
इगोरगानापोलस्की

1
जब आप एक एपीआई को संतुष्ट करना चाहते हैं जिसके लिए एक फ्लो उदाहरण के साथ LiveData की आवश्यकता होती है
शमूएल

Google के अनुसार, हमें LiveData या फ़्लो में से किसी एक को चुनना होगा : codelabs.developers.google.com/codelabs/…
IgorGanapolsky

1

3-स्तरीय आर्किटेक्चर में: डेटा-डोमेन-प्रेजेंटेशन, फ़्लो को डेटा लेयर (डेटाबेस, नेटवर्क, कैश ...) में ले जाना चाहिए और फिर सैमुअल अर्बनोविक्ज़ ने उल्लेख किया कि आप फ्लो को लाइवडेटा में मैप कर सकते हैं।

सामान्य तौर पर, RxJava के लिए फ्लो लगभग वह है जो ऑब्जर्वेबल (या फ़्लोएबल) है। इसे LiveData के साथ भ्रमित न करें।

यहाँ और अधिक: https://medium.com/@elizarov/cold-flows-hot-channels-d74769805255


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