【发布时间】:2021-12-15 19:29:55
【问题描述】:
我通过改编我的一个干净的架构应用程序开始使用 Jetpack Compose。我用这个撰写功能创建了一个底部导航栏:
@Composable
fun Navigation(navController: NavHostController){
NavHost(navController, startDestination = NavigationItem.Planes.route) {
composable(NavigationItem.Planes.route) {
PlanesScreen(hiltViewModel())
}
composable(NavigationItem.Weather.route) {
WeatherScreen()
}
composable(NavigationItem.More.route) {
MoreScreen()
}
}
}
在我的PlanesScreen 中,我使用 Hilt 方法将以下ViewModel 传递给它:
@HiltViewModel
class PlanesViewModel @Inject constructor(private val planeInfoUseCase: PlaneInfoUseCase) : ViewModel() {
fun planeInfo() : LiveData<UiResponse<ArrayList<PlaneInfo>>> {
return planeInfoUseCase.execute().toUiResponse().flowAsLiveData(Dispatchers.IO)
}
}
useCase 返回一个Flow,我将其转换为UiResponse 以表示我视图的不同状态:
fun <T> Flow<T>.toUiResponse() : Flow<UiResponse<T>>{
return this.map<T, UiResponse<T>> { UiResponse.Success(it) }
.onStart { emit(UiResponse.Loading()) }
.catch {
val t : Throwable = it
emit(UiResponse.Error(it))
}
}
PlaneScreen 屏幕包含一个可组合的方法,可以不受任何限制地显示文本
@Composable
fun PlanesScreen(viewModel : PlanesViewModel){
PlaneList(viewModel.planeInfo().observeAsState())
}
我通过observeAsSate 将LiveData 转换为State,然后将其传递给显示文本的方法。
在这一次中,我在 UiResponse 上执行我的 when 以对响应的不同状态做出反应
@Composable
fun PlaneList(state: State<UiResponse<ArrayList<PlaneInfo>>?>){
state.value.let {
when(it){
is UiResponse.Error -> Text(text = "Error")
is UiResponse.Loading -> Text(text = "Loading")
is UiResponse.Success -> it.data.forEach { Text(text = it.registration) }
}
}
}
当我编译应用程序时,屏幕包含文本Loading,然后是打印列表的结果,但是当我查看 Chuck 时,我有两次调用我的数据库。
在使用调试器时,我注意到启动 PlaneScreen 的 NavHost 的可组合项被调用了两次,这导致了我的问题。
无论我看了多少,我都找不到解决方案,以便能够将 ViewModel 传递给 NavHost 中的可组合对象,并且即使在重新组合屏幕时也只进行一次调用
您知道如何解决这个问题而不必将viewModels 传递给我的Navigation 函数吗?
【问题讨论】:
标签: android kotlin android-jetpack-compose android-viewmodel kotlin-flow