如何在 KMM 应用程序中使用collectAsState? 目前我在我的应用程序中使用它,如下所示:
用户界面:
usersViewModel.userInfo.collectAsState(null).apply {
//use data from userInfo
}
视图模型:
val userInfo = repo.getUserProfile().catch { println("no User found") }
回购:
fun getUserProfile(): Flow<User?> = flow {
try {
firestore.collection("User").document(auth.currentUser!!.uid).snapshots.collect { user ->
emit(user.data<UserInfo>())
}
}catch (ex: Exception){
println("Something wrong")
}
}
fun getAllRestaurants(): Flow<List<Restaurant>> {
val user = getUserProfile()
firestore.collection("Restaurant").snapshots.map { querySnapshot ->
val restaurants = querySnapshot.documents.map { documentSnapshot ->
documentSnapshot.data<Restaurant>()
}.filter { restaurant ->
checkIfPointInsidePolygon(user.first()!!.userLocation!!, restaurant.polygonList)
}
restaurants
}
}
目前看起来很慢,我不知道这是因为调试还是我没有以最佳方式获取实时数据。您是否还可以验证 getAllRestaurants 是否以正确的方式完成对象列表?
感谢您的帮助!
总体思路是不收集流量,而只是将它们传递到各层(可能会在途中转换它们),直到它们到达 UI。只有在那里它们最终才会被收集。
对于您的存储库,这意味着您不应该收集并重新发出该值,而只需通过映射其内容来转换流程:
fun getUserProfile(): Flow<User?> =
firestore.collection("User").document(auth.currentUser!!.uid).snapshots
.mapLatest { user ->
user.data<UserInfo>()
}
.catch { ex ->
println("Something wrong")
}
在视图模型中,您需要将流转换为 StateFlow:
val userInfo: StateFlow<User?> = repo.getUserProfile()
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = null,
)
最后在可组合项中将 StateFlow 转换为 Compose State:
val userInfo: User? by usersViewModel.userInfo.collectAsState()
(如果您希望集合具有生命周期意识,则需要使用 gradle 依赖项
collectAsStateWithLifecycle
中的 androidx.lifecycle:lifecycle-runtime-compose
来代替。)
by
委托,它允许您使用 userInfo
,就好像它是 User?
类型一样,而实际上它在幕后是一个 State<User?>
。
现在您可以使用
userInfo
变量做任何您想做的事情。 Flow 框架保证该变量始终是最新的,并且每当出现新值时就会触发 UI 的重组。