Использование карты в Stateflow Котлина
С LiveData внутри Viewmodel мы используем switchMap или Transformations.map, как это
val recipesList = cuisineType.switchMap { repository.getDisplayRecipes(it.cuisineType).asLiveData() }
Как лучше всего сделать это с помощью StateFlow? Я знаю, что мы можем просто использовать карту, как показано ниже, однако это вернет мне Flow <Flow <List <Recipe >>>, что не кажется правильным
val recipeListFlow = cuisineTypeStateFlow.map {
repository.getDisplayRecipes(it.cuisineType)
}
2 ответа
Официального способа сделать это до сих пор нет (пока), но есть разумная рекомендация 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)
}