【问题标题】:Compose ViewModel lifecycle when working with live edit使用实时编辑时编写 ViewModel 生命周期
【发布时间】:2021-09-09 16:08:35
【问题描述】:

我的主屏幕有以下代码:

@Composable
fun MainScreen() {
    val viewModel = getViewModel<MainViewModel>()
    val tasks: List<Task> by viewModel.taskList.observeAsState(listOf())
    LazyColumn(contentPadding = PaddingValues(bottom = 96.dp)) {
        items(tasks) { task ->
            if (task == tasks[0]) {
                ListItemActive(task = task)
            } else {
                ListItemInactive(task = task)
            }
        }
    }
    val isInProgress: Boolean by viewModel.isInProgress.observeAsState(false)
    if (isInProgress) {
        Preloader()
    }
}

导航在主要活动中管理,如下所示:

NavHost(navController = navController, startDestination = Screen.Main.route) {
    composable(Screen.Login.route) { LoginScreen() }
    composable(Screen.Main.route) { MainScreen() }
}

问题是,每当我在 android studio 中调整填充或其他尺寸时,我的主屏幕构图都会被重新评估。这是人们所期望的,但不是采用现有的视图模型,而是创建了新的视图模型。旧的不调用 onCleared 。这是预期的行为,还是我遗漏了什么?

编辑: 当对代码进行任何更改并且实时编辑器尝试在模拟器上更新它们时,我也会遇到崩溃。

例外:读取在拍摄快照后或尚未应用的快照中创建的状态

当访问 SharedPreferences 时,它发生在下面的代码中。此代码从视图模型中的 init 块调用,该块在代码填充更改期间第二次初始化。

httpClient.addInterceptor { chain ->
        val request: Request = chain
            .request()
            .newBuilder()
            .addHeader("Authorization", "Bearer ${get<PreferenceRepository>().accessToken}")
            .build()
        chain.proceed(request)
    }

虽然它似乎与我正在使用的 viewModelScope 相关联。将其替换为 GlobalScope 可防止应用崩溃。

【问题讨论】:

  • 一个小提示:您可以使用itemsIndexed 代替items 并比较index 而不是项目本身。
  • 您是说在您启动应用程序,然后在代码中更新PaddingValues,并且您的应用程序在没有重新启动的情况下更新?最有可能的是,在这种情况下,旧的视图模型将被简单地杀死,如果您在应用程序的正常运行期间没有遇到类似的问题,您无需担心。
  • @PhilipDukhov,感谢您的提示。是的,情况确实如此,尽管我实际上遇到了问题。我的应用程序因“读取在拍摄快照后创建的状态或在尚未应用的快照中创建的状态”而崩溃,这似乎是由访问视图模型的 init() 块中的共享首选项引起的。
  • 我相信它叫做Enable Live Edit of literals,请尝试在 AS 偏好设置中禁用它。
  • @PhilipDukhov,是的,但我希望能够使用它,因为它极大地提高了我的工作效率。现在,我只是在应用设计时注释掉了我的视图模型的 init() 方法。但我仍然想找到一个更永久的解决方案。

标签: android android-jetpack-compose koin


【解决方案1】:

Koin 3.1.2 不适用于 Navigation Compose。该错误在 GitHub 上跟踪:https://github.com/InsertKoinIO/koin/issues/1079

您也可以使用cokoin library:

@Composable
fun App() {
    val navController = rememberNavController()
    KoinNavHost(navController, startDestination = "1") {
        composable("1") {
            val navViewModel = getNavViewModel<NavViewModel>()
            //...
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 2020-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-10
    • 1970-01-01
    相关资源
    最近更新 更多