【发布时间】:2021-06-16 09:23:59
【问题描述】:
我有一个 Fragment,它代表单个 Activity 应用程序中的一个屏幕,以及一个用于该 Fragment 的 ViewModel。
ViewModel 使用多个存储库从多个 API 调用中加载一组数据,并通过 multiple StateFlow 将该数据发送到片段。
假设片段有 2 个视图,每个视图都从与其相关的 StateFlow 中收集数据。直到所有 2 个视图都没有绘制它们的数据,我想显示一些进度条,然后当这些视图接收数据时,将整个片段可见性从不可见设置为可见。
我的问题是:当所有 2 个视图都收到数据时如何正确处理?
存储库:
class Repository(private val name: String) {
private val _data = MutableStateFlow<String?>(null)
val data = _data.asStateFlow()
suspend fun load() {
// load from the DB/API if no data
// load fresh from the API if have data
delay(1000)
_data.emit("$name data")
}
}
视图模型:
class ScreenViewModel : ViewModel() {
// will be injected by Dagger2/Hilt
private val repository1 = Repository("Repository1")
private val repository2 = Repository("Repository2")
private val _flow1 = MutableStateFlow<String?>(null)
private val _flow2 = MutableStateFlow<String?>(null)
val flow1 = _flow1.asStateFlow()
val flow2 = _flow2.asStateFlow()
init {
viewModelScope.launch {
repository1.data.collect {
_flow1.emit(it)
}
}
viewModelScope.launch {
repository2.data.collect {
_flow2.emit(it)
}
}
viewModelScope.launch {
repository1.load()
}
viewModelScope.launch {
repository2.load()
}
}
}
片段:
class Screen : Fragment(/*layoutd*/) {
private val viewModel: ScreenViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
viewModel.flow1.filterNotNull().collect {
draw1(it)
}
}
viewLifecycleOwner.lifecycleScope.launch {
viewModel.flow2.filterNotNull().collect {
draw2(it)
}
}
}
private fun draw1(data: String) {
// some stuff
}
private fun draw2(data: String) {
// some stuff
}
}
【问题讨论】:
-
您可以尝试在
val call1 = async { repository1.load() }val call2 = async { repository2.load() }draw(call1.await(), call2.await())这样的延迟调用中调用您的存储库,这样可以确保在调用draw方法之前完成两个调用。为了处理状态,您可以使用 Resources 包装器或它的变体,以便您的 UI 可以区分状态。 developer.android.com/jetpack/guide#addendum
标签: android mvvm android-livedata android-viewmodel kotlin-stateflow