对于Viewmodel中的LiveData,我们使用switchMap或transforms。像这样的地图
val recipesList = cuisineType.switchMap { repository.getDisplayRecipes(it.cuisineType).asLiveData() }
用statflow做这件事的最好方法是什么?我知道我们可以像下面这样使用map,但是这将返回Flow
val recipeListFlow = cuisineTypeStateFlow.map {
repository.getDisplayRecipes(it.cuisineType)
}
目前还没有正式的方法,但是有一个合理的建议,来自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
应该是
val recipeListFlow = cuisineTypeStateFlow.flatMapLatest {
repository.getDisplayRecipes(it.cuisineType)
}