gpt4 book ai didi

android - 在 Composable 中收集转换后的 StateFlow

转载 作者:行者123 更新时间:2023-12-05 00:00:49 36 4
gpt4 key购买 nike

有函数collectAsState()适用于 StateFlow属性以便在 Composable 中观察它.

可组合项需要 StateFlow因为StateFlow保证初始值。 Flow没有这种保证。

现在,如果我有一个 StateFlow 该怎么走?属性,但我想在收集 map 之前应用一个运算符(如 Flow )在Composable

举个例子:

假设一个存储库公开了一个 StateFlow<MyClass>

val myClassStateFlow: StateFlow<MyClass>

data class MyClass(val a: String)

... 并且 View 模型依赖于存储库并且只想公开属性 a到它的Composable ...

val aFlow = myClassState.Flow.map { it.a } // <- this is of type Flow<String>

map运算符将类型从 StateFlow<MyClass> 更改为至 Flow<String> .

  1. aFlow 在语义上是否合理没有初始值了吗?毕竟它的第一次发射是从 myClassStateFlow 的初始值得出的。 .
  2. 需要转换FlowStateFlow在某一点。这是哪个更惯用的地方?
    1. 在 View 模型中使用 stateIn() ?代码会是什么样子?
    2. 在可组合项中使用 collectAsState(initial: MyClass)并得出一个初始值(尽管 myClassStateFlow 有一个初始值)?

最佳答案

参见 this issue on 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 上进行扩展,就像当前 Flow 上的 map 扩展一样

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

现在在您的 Repository 或 ViewModel 中,您可以按如下方式使用它。


class MyViewModel( ... ) {
private val originalStateFlow:StateFlow<SomeT> = ...

val someStateFlowtoExposeToCompose =
originalStateFlow
.mapState { item ->
yourTransform(item)
}
}

现在您可以在 Compose 中按预期使用它而无需任何特殊工作,因为它返回一个 StateFlow

关于android - 在 Composable 中收集转换后的 StateFlow,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70158579/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com