2

让我们把它简单化。我MutableSharedFlowsortOrder我的ViewModel.

private val sortOrder = MutableSharedFlow<String>(
    replay = 0,
    extraBufferCapacity = 1
)

每当更改时,我都会mapLatest连接到sortOrder刷新数据。sortOrder

val data = sortOrder.mapLatest {
    Timber.d("Sort order changed to $it")
    "Sort order is $it"
}

我有一个观察者在听data活动。

viewModel.data.asLiveData().observe(this) {
    Timber.d("onCreate: New data is $it")
}

最后,我改变了sortOrderinViewModelinit方法

init {
    sortOrder.tryEmit("year")
}

但即使在更改sortOrder值之后,mapLatest也不会被触发。知道为什么吗?

MutableSharedFlow用来控制replay属性以防止mapLatest每次旋转屏幕(或重新创建活动时)时执行主体。

完整的源代码

PS:我是 Flow API 的新手

4

2 回答 2

1

问题似乎是您向流发出并从中收集的顺序(使用viewModel.data.asLiveData().observe(...))。由于您在视图模型的构造中发出 (with tryEmit),因此您无法在此时观察。理论上的实现与此相同:

val sortOrder = MutableSharedFlow<String>(
    replay = 0,
    extraBufferCapacity = 1
)

val data = sortOrder.mapLatest {
    Timber.d("Sort order changed to $it")
    "Sort order is $it"
}

sortOrder.tryEmit("year")

data.asLiveData().observe(this) {
    Timber.d("onCreate: New data is $it")
}

解决方案取决于您想要的行为:

如果您对可能向新收集器发出的相同值没问题,您可以简单地设置reply = 1(然后extraBufferCapacity可以设置为0)。

另一种解决方案是确保tryEmit在调用 after 之前不调用它,并确保调用时viewModel.data.asLiveData().observe(...)活动至少处于恢复状态tryEmit,否则该值将被忽略。

于 2021-06-17T14:33:52.920 回答
0

我认为tryEmit应该避免,如果你没有重播,但仍然不希望你的事件被丢弃。

在这些情况下,我会使用emit(),在您的情况下,它将暂停直到订阅者mapLatest开始发挥作用。

同样在屏幕旋转的情况下,如果在屏幕旋转时发出事件并且您没有收听该事件,那么您将在屏幕旋转后得到它,我相信这在大多数情况下都是正确的用户体验情况,但这可能取决于

于 2021-01-12T06:31:09.257 回答