android - 共享流 : mapLatest not getting triggered

标签 android kotlin kotlin-coroutines kotlinx.coroutines.flow

让我们把这个简单化。我的 ViewModel 中有一个名为 sortOrderMutableSharedFlow

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

我有一个观察者在 Activity 中监听数据

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

最后,我更改了 ViewModelinit 方法中的 sortOrder

init {
    sortOrder.tryEmit("year")
}

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

我正在使用 MutableSharedFlow 来控制 replay 属性,以防止每次旋转屏幕时(或重新创建 Activity 时)执行 mapLatest 正文).

完整源代码

PS: I am new to Flow APIs

最佳答案

问题似乎是您发送到流并从中收集的顺序(使用 viewModel.data.asLiveData().observe(...))。由于您在 View 模型的构造中发出(使用 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).

另一个解决方案是确保 tryEmitviewModel.data.asLiveData().observe(...) 被调用之前不被调用,并确保该 Activity 至少在 resumed state当调用 tryEmit 时,否则该值将被忽略。

关于android - 共享流 : mapLatest not getting triggered,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65633219/

相关文章:

android - Jetpack 根据动态宽度撰写下一行的行项目

java - "Accidental override: The following declarations have the same JVM signature"实现Java接口(interface)时

android - 如何使用条件导航将 androidTest 添加到 fragment ?

java - ArrayList 空指针异常与条件的关系

android - 如何在底部 fragment 代码中添加滑动

android - 使用协程和 LiveData 实现 EventBus

android - 使用 kotlin 协程时使用 try catch block 吞下异常

android-fragments - 获取房间数据库提供的 "Refresh"LiveData 的最佳方法

android - 同时运行多个测试时测试失败

android - 如何在Android gradle中使用嵌套依赖?