StateFlow এবং SharedFlow

StateFlow এবং SharedFlow হল ফ্লো API যা ফ্লোকে সর্বোত্তমভাবে স্টেট আপডেট নির্গত করতে এবং একাধিক ভোক্তাদের কাছে মান নির্গত করতে সক্ষম করে।

StateFlow

StateFlow হল একটি স্টেট-হোল্ডার পর্যবেক্ষণযোগ্য প্রবাহ যা বর্তমান এবং নতুন স্টেট আপডেটগুলি তার সংগ্রাহকদের কাছে প্রকাশ করে। বর্তমান রাষ্ট্র মান তার value সম্পত্তি মাধ্যমে পড়া যেতে পারে. স্টেট আপডেট করতে এবং ফ্লোতে পাঠাতে, MutableStateFlow ক্লাসের value সম্পত্তিতে একটি নতুন মান বরাদ্দ করুন।

অ্যান্ড্রয়েডে, StateFlow সেই ক্লাসগুলির জন্য একটি দুর্দান্ত ফিট যা একটি পর্যবেক্ষণযোগ্য পরিবর্তনযোগ্য অবস্থা বজায় রাখতে হবে।

Kotlin ফ্লো থেকে উদাহরণগুলি অনুসরণ করে, একটি StateFlow LatestNewsViewModel থেকে উন্মুক্ত করা যেতে পারে যাতে View UI অবস্থার আপডেট শুনতে পারে এবং অন্তর্নিহিতভাবে স্ক্রিন স্টেটকে কনফিগারেশন পরিবর্তনগুলিকে বাঁচিয়ে রাখতে পারে৷

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 তা করে না।
  • 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 ফাংশনও থাকে যদি আপনি ফ্লোতে পাঠানো সর্বশেষ তথ্য রিপ্লে করতে না চান।

অতিরিক্ত প্রবাহ সম্পদ