[英]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例如在您的第一个代码块中,我会像这样更改它
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.