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

Avoid repetitive launch when emitting value using Flow, StateFlow, SharedFlow

我正在从 LiveData 迁移到协程流,特别是 StateFlowSharedFlow。不幸的是,在 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))
        }
    }

}

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

请注意,您当前没有缓冲区,因为您将 replay 保留为 0。您应该至少保留 1 的重放,这样当您的配置发生更改时不会丢失值Activity/Fragment.

示例:

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

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