简体   繁体   English

如何结合 livedata 和 kotlin 流

[英]How to combine livedata and kotlin flow

Is this good to put the collect latest inside observe?把最新的收藏放在里面观察这样好吗?

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)
                        }
                    }
                }
            }

OR或者

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???
                    }
                }
            }
        }

I'm sure it isn't, my API is called thrice too as the local DB changes, what is the right way to do this?我确定不是,我的 API 在本地数据库更改时也被调用了三次,正确的方法是什么?

it certainly is not a good practice to put a collect inside the observe.在观察中放置一个收集当然不是一个好习惯。

I think what you should do is collect your livedata/flows inside your viewmodel and expose the 'state' of your UI from it with different values (either Flows or Livedata)我认为您应该做的是在您的视图模型中收集您的实时数据/流,并使用不同的值(流或实时数据)从中公开您的 UI 的“状态”

for example in your first code block I would change it like this例如在您的第一个代码块中,我会像这样更改它

  • get rid of "userProfile" from your viewmodel从您的视图模型中删除“userProfile”
  • create and expose from your viewmodel to your activity three LiveData/StateFlow objects for your communityFeedPageData, errorMessage, refreshingState为您的 communityFeedPageData、errorMessage、refreshState 创建并从您的视图模型向您的活动公开三个 LiveData/StateFlow 对象
  • then in your viewmodel, where you would update the "userProfile" update the three new LiveDatas然后在您的视图模型中,您将在其中更新“userProfile”更新三个新的 LiveData

this way you will take the business logic of "what to do in each state" outside from your activity and inside your viewmodel, and your Activity's job will become to only update your UI based on values from your viewmodel这样,您将从您的活动之外和您的视图模型内部获取“在每个状态下做什么”的业务逻辑,并且您的活动的工作将变成仅根据您的视图模型中的值更新您的 UI

For the specific case of your errorMessage and because you want to show it only once and not re-show it on Activity rotation, consider exposing a hot flow like this:对于您的 errorMessage 的特定情况,并且因为您只想显示一次而不是在 Activity 轮换中重新显示它,请考虑公开这样的热流:

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

What "receiveAsFlow()" does really nicely is that something emitted to the channel will be collected by one collector only, so a new collector (eg if your activity recreates on a rotation) will not gether the message and your user will not see it again “receiveAsFlow()” 做得很好的是,发送到通道的内容将仅由一个收集器收集,因此新的收集器(例如,如果您的活动在旋转时重新创建)将不会收集消息并且您的用户将看不到它再次

You can combine both streams of data into one stream and use their results.您可以将两个数据流合并为一个 stream 并使用它们的结果。 For example we can convert LiveData to Flow , using LiveData.asFlow() extension function, and combine both flows:例如,我们可以使用LiveData.asFlow()扩展 function 将LiveData转换为Flow ,并combine两个流:

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

But it is better to move combining logic to ViewModel class and observe the overall result.但最好将组合逻辑移至ViewModel class 并观察整体结果。

Dependency to use LiveData.asFlow() extension function:使用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