मेरे पास मेरे व्यू मॉडल में 2 स्टेटफ्लो हैं। उन्हें टुकड़े में इकट्ठा करने के लिए मुझे नीचे के रूप में 2 बार कोरटाइन लॉन्च करना होगा:

    lifecycleScope.launchWhenStarted {
        stocksVM.quotes.collect {
            if (it is Resource.Success) {
                it.data?.let { list ->
                    quoteAdapter.submitData(list)
                }
            }
        }
    }

    lifecycleScope.launchWhenStarted {
        stocksVM.stockUpdate.collect {
            log(it.data?.data.toString())
        }
    }

अगर मेरे पास अधिक राज्य प्रवाह है, तो मुझे क्रमशः कोरआउट लॉन्च करना होगा। क्या मेरे फ्रैगमेंट/गतिविधि में या कहीं भी एकाधिक स्टेटफ्लो को संभालने का कोई बेहतर तरीका है?

5
Azim Salimov 2 जून 2021, 09:16
आपको एक दायरे में इकट्ठा करने से क्या रोक रहा है? जैसे अगर आप lifecycleScope.launchWhenStarted {} लॉन्च करते हैं तो क्या आप इसके अंदर ही stocksVM.quotes.collect{} और stocksVM.stockUpdate.collect {} नहीं कर सकते।
 – 
che10
2 जून 2021, 09:21
दुर्भाग्य से, मैं नहीं कर सकता। क्योंकि कलेक्ट () एक कोरटाइन के अंदर एक सस्पेंडिंग फंक्शन है और यह तब तक सस्पेंड रहेगा जब तक मेरा फ्लो बंद नहीं हो जाता, इस प्रकार मेरा अगला कलेक्ट () तब तक नहीं कहा जाएगा जब तक कि पिछला फ्लो @ che10 समाप्त नहीं हो जाता।
 – 
Azim Salimov
3 जून 2021, 10:30

4 जवाब

सबसे बढ़िया उत्तर

आपको अलग-अलग कोरआउट की आवश्यकता होगी, क्योंकि collect() एक निलंबित कार्य है जो आपके Flow के समाप्त होने तक निलंबित रहता है।

एकाधिक प्रवाह एकत्र करने के लिए वर्तमान में अनुशंसित तरीका है:

lifecycleScope.launch {
    lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
        launch {
          stocksVM.quotes.collect { ... }   
        }
    
        launch {
            stocksVM.stockUpdate.collect { ... }
        }
    }
}

ध्यान दें कि launchWhenStarted के साथ समस्या यह है कि जब आपके नए उत्सर्जित आइटम संसाधित नहीं होंगे, तब भी आपका निर्माता पृष्ठभूमि में चलेगा।

मैं निश्चित रूप से इसे पढ़ूंगा, क्योंकि यह वर्तमान सर्वोत्तम प्रथाओं को वास्तव में अच्छी तरह से समझाता है: https://medium.com/androiddevelopers/a-safer-way-to-collect-flows-from-android-uis-23080b1f8bda

9
Róbert Nagy 2 जून 2021, 10:55
सहायता के लिए धन्यवाद! मैं इसे जरूर पढ़ूंगा
 – 
Azim Salimov
2 जून 2021, 15:36

आप कई धाराओं को मिलाना चुन सकते हैं।

kotlin में फ़ंक्शन merge या combine का उपयोग करें। बेशक, इन दोनों कार्यों का उपयोग अलग है।


जोड़ें:

यदि प्रवाह संसाधित नहीं होता है, तो एकत्र करने के लिए कई कोरआउट खोलें ():

fun main() {
    collectFlow()
}

fun emitStringElem(): Flow<String> = flow {
    repeat(5) {
        delay(10)
        emit("elem_$it")
    }
}

fun emitIntElem(): Flow<Int> = flow {
    repeat(10) {
        delay(10)
        emit(it)
    }
}

दो coroutine संग्रह खोलें परिणाम है:

From int Flow: item is: 0
From string Flow: item is: elem_0
From int Flow: item is: 1
From string Flow: item is: elem_1
From int Flow: item is: 2
From string Flow: item is: elem_2
From int Flow: item is: 3
From string Flow: item is: elem_3
From int Flow: item is: 4
From string Flow: item is: elem_4
From int Flow: item is: 5
From int Flow: item is: 6
From int Flow: item is: 7
From int Flow: item is: 8
From int Flow: item is: 9

दो प्रवाह मर्ज करें

fun margeFlow() = runBlocking {
    merge(
        emitIntElem().map {
            it.toString()
        }, emitStringElem()
    ).collect {
        println(it)
    }
}

परिणाम है:

0
elem_0
1
elem_1
2
elem_2
3
elem_3
4
elem_4
5
6
7
8
9

दो प्रवाह को मिलाएं:

fun combineFlow() = runBlocking {
    combine(emitIntElem(), emitStringElem()) { int: Int, str: String ->
        "$int combine $str"
    }.collect {
        println(it)
    }
}

परिणाम है:

0 combine elem_0
1 combine elem_0
1 combine elem_1
2 combine elem_2
3 combine elem_3
4 combine elem_4
5 combine elem_4
6 combine elem_4
7 combine elem_4
8 combine elem_4
9 combine elem_4
2
Future Deep Gone 2 जून 2021, 10:07
सहायता के लिए धन्यवाद। मैं उस पर विचार करूंगा
 – 
Azim Salimov
2 जून 2021, 15:37

जैसे @RobertNagy ने कहा, आपको launchWhenStarted का उपयोग नहीं करना चाहिए। लेकिन नेस्टेड launches को किए बिना इसे उचित तरीके से करने के लिए एक वैकल्पिक सिंटैक्स है:

stocksVM.quotes
    .flowOnLifecycle(Lifecycle.State.STARTED)
    .onEach { 
        if (it is Resource.Success) {
            it.data?.let { list ->
                quoteAdapter.submitData(list)
            }
        }
    }.launchIn(lifecycleScope)

stocksVM.stockUpdate
    .flowOnLifecycle(Lifecycle.State.STARTED)
    .onEach { 
        log(it.data?.data.toString())
    }.launchIn(lifecycleScope)
2
Tenfour04 2 जून 2021, 16:42
सहायता के लिए धन्यवाद!
 – 
Azim Salimov
2 जून 2021, 16:52
मेरे जवाब यहां देखें ताकि एक ऐसे हेल्पर फंक्शन के लिए जो सिंटैक्स को बहुत अच्छा बना सके संक्षिप्त।
 – 
Tenfour04
2 जून 2021, 18:28

अगर कोई सोच रहा है कि viewModelScope.launch के एक ही ब्लॉक में एकाधिक प्रवाह कैसे उत्सर्जित किया जाए, तो यह रॉबर्ट के उत्तर के समान ही है। यानी इस प्रकार है

viewModelScope.launch {
    launch {
        exampleFlow1.emit(data)
    }
    launch {
        exampleFlow2.emit(data)
    }
}
1
Rawlin Crasto 8 सितंबर 2021, 18:22