在 Kotlin 的 Stateflow 上使用地图

问题描述 投票:0回答:2

在 Viewmodel 中使用 LiveData,我们像这样使用 switchMap 或 Transformations.map

val recipesList = cuisineType.switchMap { repository.getDisplayRecipes(it.cuisineType).asLiveData() }

使用 StateFlow 执行此操作的最佳方法是什么?我知道我们可以像下面这样使用地图,但是这会让我返回 Flow>> 这似乎不正确

val recipeListFlow = cuisineTypeStateFlow.map {
    repository.getDisplayRecipes(it.cuisineType)
}
android kotlin viewmodel android-livedata kotlin-stateflow
2个回答
1
投票

应该是

val recipeListFlow = cuisineTypeStateFlow.flatMapLatest {
    repository.getDisplayRecipes(it.cuisineType)
}

0
投票

仍然没有官方的方法来做到这一点(但是)但是有一个合理的建议来自https://github.com/Kotlin/kotlinx.coroutines/issues/2631#issuecomment-870565860

/**
 * Does not produce the same value in a raw, so respect "distinct until changed emissions"
 * */
class DerivedStateFlow<T>(
    private val getValue: () -> T,
    private val flow: Flow<T>
) : StateFlow<T> {

    override val replayCache: List<T>
        get () = listOf(value)

    override val value: T
        get () = getValue()

    @InternalCoroutinesApi
    override suspend fun collect(collector: FlowCollector<T>): Nothing {
        coroutineScope { flow.distinctUntilChanged().stateIn(this).collect(collector) }
    }
}

fun <T1, R> StateFlow<T1>.mapState(transform: (a: T1) -> R): StateFlow<R> {
    return DerivedStateFlow(
        getValue = { transform(this.value) },
        flow = this.map { a -> transform(a) }
    )
}

fun <T1, T2, R> combineStates(flow: StateFlow<T1>, flow2: StateFlow<T2>, transform: (a: T1, b: T2) -> R): StateFlow<R> {
    return DerivedStateFlow(
        getValue = { transform(flow.value, flow2.value) },
        flow = combine(flow, flow2) { a, b -> transform(a, b) }
    )
}

// and so on
© www.soinside.com 2019 - 2024. All rights reserved.