函数collectAsState()适用于StateFlow属性,以便在Composable中观察它。
可组合需要StateFlow,因为StateFlow保证初始值。Flow并没有提供这样的保证。
现在,如果我有一个StateFlow属性,但是我想在收集Composable中的Flow之前应用一个操作符(比如map),那么该怎么做呢?
这里有一个例子:
假设存储库公开了一个StateFlow<MyClass>
val myClassStateFlow: StateFlow<MyClass>
data class MyClass(val a: String)..。视图模型依赖于存储库,并且只希望将属性a公开给它的Composable.
val aFlow = myClassState.Flow.map { it.a } // <- this is of type Flow<String>map运算符将类型从StateFlow<MyClass>更改为Flow<String>。
aFlow不再具有初始值,这在语义上是合理的吗?毕竟,它的第一次发射来自于myClassStateFlow的初始值。Flow转换回StateFlow。哪个地方更惯用呢?stateIn()?代码会是什么样子?collectAsState(initial: MyClass)并给出一个初始值(尽管myClassStateFlow有一个初始值)?发布于 2021-12-16 11:04:31
请参阅GitHub上的这个问题
目前还没有内置的方式来转换StateFlow,只有Flow,但是您可以自己编写。
我最终解决的方法是在那篇文章中使用这个例子。
首先创建一个DerivedStateFlow的概念。
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>) {
flow.collect(collector)
}
}然后在StateFlow上有一个扩展,就像当前map扩展在Flow上一样
fun <T1, R> StateFlow<T1>.mapState(transform: (a: T1) -> R): StateFlow<R> {
return DerivedStateFlow(
getValue = { transform(this.value) },
flow = this.map { a -> transform(a) }
)
}现在,在您的存储库或ViewModel中,您可以如下所示使用它。
class MyViewModel( ... ) {
private val originalStateFlow:StateFlow<SomeT> = ...
val someStateFlowtoExposeToCompose =
originalStateFlow
.mapState { item ->
yourTransform(item)
}
}现在,您可以像您在撰写中所期望的那样使用它,而无需任何特殊的工作,因为它返回一个StateFlow。
https://stackoverflow.com/questions/70158579
复制相似问题