使用 Flow、StateFlow、SharedFlow 发布价值时避免重复启动

发布于 2025-01-09 18:07:51 字数 849 浏览 0 评论 0原文

我正在从 LiveData 迁移到协程流,特别是 StateFlow 和 SharedFlow。不幸的是,发出值应该在 CoroutineScope 上运行,因此在 ViewModel 中使用它时,您会遇到丑陋的重复代码 viewModelScope.launch 。是否有一种最佳的方式来释放价值?

class MainSharedViewModel : BaseViewModel() {

    private val mainActivityState = MutableSharedFlow<MainActivityState>()

    fun getMainActivityState(): SharedFlow<MainActivityState> = mainActivityState

    fun setTitle(title: String){
        viewModelScope.launch {
            mainActivityState.emit(ToolbarTitleState(title))
        }
    }

    fun filterData(assetName: String){
        viewModelScope.launch {
            mainActivityState.emit(AssetFilterState(assetName))
        }
    }

    fun limitData(limit: Int){
        viewModelScope.launch {
            mainActivityState.emit(AssetLimitState(limit))
        }
    }

}

I am migrating from LiveData to Coroutine Flows specifically StateFlow and SharedFlow. Unfortunately emitting values should run on a CoroutineScope thus you have this ugly repetitive code viewModelScope.launch when using it inside a ViewModel. Is there an optimal way of emitting values from this?

class MainSharedViewModel : BaseViewModel() {

    private val mainActivityState = MutableSharedFlow<MainActivityState>()

    fun getMainActivityState(): SharedFlow<MainActivityState> = mainActivityState

    fun setTitle(title: String){
        viewModelScope.launch {
            mainActivityState.emit(ToolbarTitleState(title))
        }
    }

    fun filterData(assetName: String){
        viewModelScope.launch {
            mainActivityState.emit(AssetFilterState(assetName))
        }
    }

    fun limitData(limit: Int){
        viewModelScope.launch {
            mainActivityState.emit(AssetLimitState(limit))
        }
    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

信仰 2025-01-16 18:07:51

使用 tryEmit() 而不是 emit()tryEmit() 是非挂起的。它“尝试”的原因是,如果流的缓冲区当前已满并设置为 SUSPEND,则它不会发出,而不是在满时丢弃值。

请注意,您当前没有缓冲区,因为您将 replay 保留为 0。您应该将重播保持至少 1,这样当配置发生更改时就不会丢失值您的活动/片段。

示例:

fun setTitle(title: String){
    mainActivityState.tryEmit(ToolbarTitleState(title))
}

或者,您可以使用 MutableStateFlow,它的重播始终为 1,并且可以使用 value = 设置其值,就像 LiveData 一样。

Use tryEmit() instead of emit(). tryEmit() is non-suspending. The reason it's "try" is that it won't emit if the flow's buffer is currently full and set to SUSPEND instead of dropping values when full.

Note, you have no buffer currently because you left replay as 0. You should keep a replay of at least 1 so values aren't missed when there is a configuration change on your Activity/Fragment.

Example:

fun setTitle(title: String){
    mainActivityState.tryEmit(ToolbarTitleState(title))
}

Alternatively, you can use MutableStateFlow, which always has a replay of 1 and can have its value set by using value =, just like a LiveData.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文