StateFlow और SharedFlow

StateFlow और SharedFlow फ़्लो एपीआई हैं जो स्थिति अपडेट को बेहतर तरीके से छोड़ने और एक से ज़्यादा उपभोक्ताओं को सुरक्षित रखना है.

StateFlow

StateFlow स्टेट-होल्डर ऑब्ज़र्वेबल फ़्लो है, जो मौजूदा और नई स्थिति का उत्सर्जन करता है के बारे में अपडेट देते हैं. वर्तमान स्थिति मान को इसके माध्यम से भी पढ़ा जा सकता है value प्रॉपर्टी. स्थिति अपडेट करने और उसे फ़्लो में भेजने के लिए, इसकी value प्रॉपर्टी MutableStateFlow क्लास.

Android में, StateFlow उन क्लास के लिए सबसे सही है जिन्हें मैनेज करने की ज़रूरत होती है ऐसी बदली हुई स्थिति हो सकती है जिसका पता लगाया जा सके.

Kotlin फ़्लो से लिए गए उदाहरणों के हिसाब से, StateFlow LatestNewsViewModel से दिखाया जा सकता है, ताकि View यूज़र इंटरफ़ेस (यूआई) की स्थिति से जुड़े अपडेट सुनें और इस वजह से स्क्रीन की मौजूदा स्थिति को बनाए रखें कॉन्फ़िगरेशन में बदलाव किए गए हैं.

class LatestNewsViewModel(
    private val newsRepository: NewsRepository
) : ViewModel() {

    // Backing property to avoid state updates from other classes
    private val _uiState = MutableStateFlow(LatestNewsUiState.Success(emptyList()))
    // The UI collects from this StateFlow to get its state updates
    val uiState: StateFlow<LatestNewsUiState> = _uiState

    init {
        viewModelScope.launch {
            newsRepository.favoriteLatestNews
                // Update View with the latest favorite news
                // Writes to the value property of MutableStateFlow,
                // adding a new element to the flow and updating all
                // of its collectors
                .collect { favoriteNews ->
                    _uiState.value = LatestNewsUiState.Success(favoriteNews)
                }
        }
    }
}

// Represents different states for the LatestNews screen
sealed class LatestNewsUiState {
    data class Success(val news: List<ArticleHeadline>): LatestNewsUiState()
    data class Error(val exception: Throwable): LatestNewsUiState()
}

MutableStateFlow को अपडेट करने के लिए ज़िम्मेदार क्लास, प्रोड्यूसर है. और StateFlow से इकट्ठा की जा रही सभी क्लास के उपभोक्ता हैं. नापसंद करें flow बिल्डर का इस्तेमाल करके बनाया गया कोल्ड फ़्लो, StateFlow हॉट होता है: फ़्लो से इकट्ठा करने पर, कोई प्रोड्यूसर कोड ट्रिगर नहीं होता. StateFlow हमेशा ऐक्टिव रहता है और मेमोरी में मौजूद होता है. साथ ही, यह बेकार डेटा पाने की ज़रूरी शर्तें पूरी करता है सिर्फ़ तब इकट्ठा करना, जब किसी कूड़े से इसका कोई और रेफ़रंस न हो कलेक्शन रूट शामिल है.

जब कोई नया उपभोक्ता, फ़्लो से डेटा इकट्ठा करना शुरू करता है, तो उसे आखिरी और उसके बाद की स्थितियों में इस्तेमाल किया जा सकता है. आप इस व्यवहार को देख सकते हैं निगरानी की जा सकती है, जैसे कि LiveData.

View अन्य फ़्लो की तरह ही, StateFlow को सुनता है:

class LatestNewsActivity : AppCompatActivity() {
    private val latestNewsViewModel = // getViewModel()

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        // Start a coroutine in the lifecycle scope
        lifecycleScope.launch {
            // repeatOnLifecycle launches the block in a new coroutine every time the
            // lifecycle is in the STARTED state (or above) and cancels it when it's STOPPED.
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                // Trigger the flow and start listening for values.
                // Note that this happens when lifecycle is STARTED and stops
                // collecting when the lifecycle is STOPPED
                latestNewsViewModel.uiState.collect { uiState ->
                    // New value received
                    when (uiState) {
                        is LatestNewsUiState.Success -> showFavoriteNews(uiState.news)
                        is LatestNewsUiState.Error -> showError(uiState.exception)
                    }
                }
            }
        }
    }
}

किसी भी फ़्लो को StateFlow में बदलने के लिए, stateIn इंटरमीडिएट ऑपरेटर.

StateFlow, फ़्लो, और LiveData

StateFlow और LiveData के पास समानताएं. दोनों, मॉनिटर किए जा सकने वाले डेटा होल्डर क्लास हैं और दोनों आपके ऐप्लिकेशन के आर्किटेक्चर में इस्तेमाल किया जाने पर मिलता-जुलता पैटर्न.

हालांकि, ध्यान दें कि StateFlow और LiveData अलग-अलग तरह से काम करते हैं:

  • StateFlow को कंस्ट्रक्टर में पास करने के लिए, एक शुरुआती स्थिति की ज़रूरत होती है, जबकि LiveData नहीं करता है.
  • LiveData.observe() में उपभोक्ता का रजिस्ट्रेशन अपने-आप रद्द हो जाता है. ऐसा तब होता है, जब व्यू, STOPPED राज्य को जाता है. वहीं, StateFlow या कोई भी अन्य फ़्लो अपने-आप इकट्ठा होना बंद नहीं करता. लक्ष्य हासिल करने के लिए बिहेवियर, आपको Lifecycle.repeatOnLifecycle से फ़्लो इकट्ठा करना होगा ब्लॉक.

shareIn का इस्तेमाल करके कोल्ड फ़्लो को गर्म करना

StateFlow एक हॉट फ़्लो है—यह तब तक मेमोरी में बना रहता है, जब तक फ़्लो बना रहता है इकट्ठा किए गए कॉन्टेंट या इसका कोई अन्य रेफ़रंस, कचरा इकट्ठा करने से जुड़े हों रूट डालें. कोल्ड फ़्लो को गर्म करने के लिए, shareIn ऑपरेटर का इस्तेमाल करें.

Kotlin फ़्लो में बनाए गए callbackFlow का इस्तेमाल उदाहरण के लिए, हर कलेक्टर से नया फ़्लो बनाने के बजाय, shareIn का इस्तेमाल करके, कलेक्टर के बीच Firestore से हासिल किया गया डेटा. आपको यह सर्टिफ़िकेट जारी करना होगा:

  • फ़्लो को शेयर करने के लिए इस्तेमाल किया जाने वाला CoroutineScope. यह स्कोप लाइव होना चाहिए किसी भी उपभोक्ता से ज़्यादा समय तक.
  • हर नए कलेक्टर को फिर से चलाने के लिए आइटम की संख्या.
  • शुरुआती व्यवहार की नीति.
class NewsRemoteDataSource(...,
    private val externalScope: CoroutineScope,
) {
    val latestNews: Flow<List<ArticleHeadline>> = flow {
        ...
    }.shareIn(
        externalScope,
        replay = 1,
        started = SharingStarted.WhileSubscribed()
    )
}

इस उदाहरण में, latestNews फ़्लो, उत्सर्जित आखिरी आइटम को फिर से चलाता है नए कलेक्टर के तौर पर जुड़ जाता है और तब तक ऐक्टिव रहता है, जब तक externalScope और कलेक्टर सक्रिय हैं. SharingStarted.WhileSubscribed() शुरुआती नीति चालू रहने पर भी, अपस्ट्रीम प्रोड्यूसर को ऐक्टिव रखती है सदस्य. शुरू करने की अन्य नीतियां उपलब्ध हैं, जैसे कि तुरंत प्रोड्यूसर बनाने के लिए SharingStarted.Eagerly या पहला सदस्य दिखने के बाद, शेयर करने के लिए SharingStarted.Lazily और फ़्लो को हमेशा चालू रखें.

शेयर किया गयाफ़्लो

shareIn फ़ंक्शन, SharedFlow दिखाता है. यह ऐसा हॉट फ़्लो होता है जिससे वैल्यू निकलती हैं कितना फ़ायदा हो सकता है. SharedFlow StateFlow को आसानी से कॉन्फ़िगर किया जा सकता है.

shareIn का इस्तेमाल किए बिना भी SharedFlow बनाया जा सकता है. उदाहरण के लिए, अगर आपने ऐप्लिकेशन के बाकी हिस्सों में टिक भेजने के लिए, SharedFlow का इस्तेमाल कर सके सभी कॉन्टेंट एक ही समय पर, समय-समय पर रीफ़्रेश होता रहता है. इसके अलावा ताज़ा समाचार लाने के लिए, हो सकता है कि आप उपयोगकर्ता को रीफ़्रेश भी करना चाहें जानकारी वाले सेक्शन में बदलाव करें. निम्न में कोड स्निपेट, TickHandler एक SharedFlow दिखाता है, ताकि अन्य क्लास को यह पता होता है कि उसका कॉन्टेंट कब रीफ़्रेश करना है. StateFlow की तरह ही, इसका इस्तेमाल करें: आइटम भेजने के लिए क्लास में MutableSharedFlow टाइप की प्रॉपर्टी का बैक अप लेना फ़्लो के लिए:

// Class that centralizes when the content of the app needs to be refreshed
class TickHandler(
    private val externalScope: CoroutineScope,
    private val tickIntervalMs: Long = 5000
) {
    // Backing property to avoid flow emissions from other classes
    private val _tickFlow = MutableSharedFlow<Unit>(replay = 0)
    val tickFlow: SharedFlow<Event<String>> = _tickFlow

    init {
        externalScope.launch {
            while(true) {
                _tickFlow.emit(Unit)
                delay(tickIntervalMs)
            }
        }
    }
}

class NewsRepository(
    ...,
    private val tickHandler: TickHandler,
    private val externalScope: CoroutineScope
) {
    init {
        externalScope.launch {
            // Listen for tick updates
            tickHandler.tickFlow.collect {
                refreshLatestNews()
            }
        }
    }

    suspend fun refreshLatestNews() { ... }
    ...
}

SharedFlow के काम करने के तरीके को अपनी पसंद के मुताबिक बनाने के लिए, ये तरीके अपनाएं:

  • replay आपको नई वैल्यू के लिए, पहले से जनरेट की गई वैल्यू फिर से भेजने की सुविधा देता है सदस्य.
  • onBufferOverflow की मदद से, बफ़र को चालू करने से जुड़ी नीति तय की जा सकती है भेजे जाने वाले आइटम से भरा हुआ है. डिफ़ॉल्ट मान BufferOverflow.SUSPEND है, इससे कॉलर को निलंबित कर दिया जाता है. अन्य विकल्प हैं: DROP_LATEST या DROP_OLDEST.

MutableSharedFlow के पास एक subscriptionCount प्रॉपर्टी भी है, जिसमें यह शामिल है सक्रिय कलेक्टर की संख्या का इस्तेमाल करें, ताकि आप अपने कारोबार को ऑप्टिमाइज़ कर सकें तर्क की ज़रूरत होती है. MutableSharedFlow में एक resetReplayCache भी शामिल है फ़ंक्शन का उपयोग करें.

फ़्लो के अन्य संसाधन