我有一个获取数据的常见情况,我使用Kotlin协程。
1个变体:
class SomeViewModel(
private val gettingData: GetDataUseCase
) : ViewModel() {
lateinit var data: List<String>
init {
viewModelScope.launch {
data = gettingData.get()
}
}
}
2个变体:
class SomeViewModel(
private val gettingData: GetDataUseCase
) : ViewModel() {
val data = MutableStateFlow<List<String>?>(null)
init {
viewModelScope.launch {
data.emit(gettingData.get())
}
}
}
我怎样才能用viewModelScope初始化一个数据域不是延迟的,而是立即的,但是没有lateinit或者nullble域?没有LiveData,我的progect使用CoroutineFlow
我无法在.run{}中或通过lazy {}返回viewModelScope作业的结果。我无法从fun返回结果:
val data: List<String> = getData()
fun getData(): List<String> {
viewModelScope.launch {
data = gettingData.get()
}
return ???
}
此外,我无法使suspend有趣getData(),因为我无法在初始化中创建协程范围'
2条答案
按热度按时间vdzxcuhz1#
您必须使用SharedFlow和replay 1(存储最后一个值并为新订阅者重放它)来实现它。
我的样品:
jdzmm42g2#
你在描述一种不可能性,假设
gettingData.get()
被定义为一个suspend函数,这意味着结果不能被立即检索,因为检索需要一段时间,所以你不能有一个immediate值。这就是为什么应用程序和网站的用户界面中有加载指示器。
如果您使用的是Flow,则可以使用可为空类型的Flow(如上面的选项2),并且在Activity/Fragment中,在收集器中,您可以根据其是否为空来显示加载指示器或数据。
您的代码2可以使用
flow
构建器和默认值为空的stateIn
来简化:在您的Activity或Fragment中:
如果你的数据加载速度很快,你可以直接设置默认值
emptyList()
,而不是让类型为空,这样当列表为空时,你的收集器就什么都不做了。如果数据加载速度足够快,用户不会因为屏幕空白太久而怀疑是否出了问题,这就可以了。