簡體   English   中英

如何結合 livedata 和 kotlin 流

[英]How to combine livedata and kotlin flow

把最新的收藏放在里面觀察這樣好嗎?

viewModel.userProfile.observe(viewLifecycleOwner){
            when(it){
                is NetworkState.Error -> Timber.e(it.error)
                is NetworkState.Loading -> {}
                is NetworkState.Success -> {
                    viewLifecycleOwner.lifecycleScope.launch {
                        viewModel.getCommunityFeed(it.data?.groups?.get(0)?.slug).collectLatest { communityFeedPageData->
                            binding.swipeRefreshFeed.isRefreshing = false
                            communityFeedAdapter.submitData(communityFeedPageData)
                        }
                    }
                }
            }

或者

viewModel.fetchUserProfileLocal(PreferencesManager(requireContext()).userName!!)
            .observe(viewLifecycleOwner) {
                if (!it.groups.isNullOrEmpty()) {
        viewLifecycleOwner.lifecycleScope.launch {
            viewModel.referralDetailsResponse.collect { referralResponseState ->
                when (referralResponseState) {
                    State.Empty -> {
                    }
                    is State.Failed -> {}
                    State.Loading -> {}
                    is State.Success<*> -> {
                        if (it.groups.isEmpty())
                            // ACCESS LIVEDATA OBSERVABLE RESULT LIKE THIS???
                    }
                }
            }
        }

我確定不是,我的 API 在本地數據庫更改時也被調用了三次,正確的方法是什么?

在觀察中放置一個收集當然不是一個好習慣。

我認為您應該做的是在您的視圖模型中收集您的實時數據/流,並使用不同的值(流或實時數據)從中公開您的 UI 的“狀態”

例如在您的第一個代碼塊中,我會像這樣更改它

  • 從您的視圖模型中刪除“userProfile”
  • 為您的 communityFeedPageData、errorMessage、refreshState 創建並從您的視圖模型向您的活動公開三個 LiveData/StateFlow 對象
  • 然后在您的視圖模型中,您將在其中更新“userProfile”更新三個新的 LiveData

這樣,您將從您的活動之外和您的視圖模型內部獲取“在每個狀態下做什么”的業務邏輯,並且您的活動的工作將變成僅根據您的視圖模型中的值更新您的 UI

對於您的 errorMessage 的特定情況,並且因為您只想顯示一次而不是在 Activity 輪換中重新顯示它,請考慮公開這樣的熱流:

private val errorMessageChannel = Channel<CharSequence>()
val errorMessageFlow = errorMessageChannel.receiveAsFlow()

“receiveAsFlow()” 做得很好的是,發送到通道的內容將僅由一個收集器收集,因此新的收集器(例如,如果您的活動在旋轉時重新創建)將不會收集消息並且您的用戶將看不到它再次

您可以將兩個數據流合並為一個 stream 並使用它們的結果。 例如,我們可以使用LiveData.asFlow()擴展 function 將LiveData轉換為Flow ,並combine兩個流:

combine(
  viewModel.fetchUserProfileLocal(PreferencesManager(requireContext()).userName!!),
  viewModel.referralDetailsResponse
) { userProfile, referralResponseState  ->
  ...
}.launchIn(viewLifecycleOwner.lifecycleScope)

但最好將組合邏輯移至ViewModel class 並觀察整體結果。

使用LiveData.asFlow()擴展 function 的依賴關系:

implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.0"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM