J. *_*Doe 5 android kotlin android-jetpack-compose
我正在创建一个聊天应用程序,当用户离开聊天时我需要执行逻辑(聊天只是一个@Composable fun,我正在LocalLifecycleOwner.current与 ViewModel 结合使用,ViewModel 监视onDestroy取消订阅用户的方法)。现在,当用户更改选项卡时也会执行逻辑,因此不应发生这种情况。
我正在使用 aScaffold和 a BottomNavigation。当我切换选项卡时,旧选项卡将被销毁。我不希望出现这种行为,旧选项卡应该保留在内存中。remember返回选项卡时,这些块也会重新执行,我不希望这样。我应该使用多个导航主机还是其他什么?
在选项卡之间导航而不remember重新执行块(也不LocalLifecycleOwner.current应该发布onDestroy)。
整个项目可以在这里找到: https: //github.com/Jasperav/JetpackComposeNavigation。您可以看到,当切换选项卡时,remember块会重新执行,并且会被VM销毁(请参阅日志记录)。我不想要这种行为,它应该被保留在记忆中。这是相关代码:
@Composable
fun Screen() {
val items = listOf(
Triple("a", Icons.Default.Person, Icons.Filled.Person),
Triple("b", Icons.Default.Notifications, Icons.Filled.Notifications),
)
var selectedTab = items[0]
val navHostController = rememberNavController()
Scaffold(
bottomBar = {
BottomNavigation {
items.forEachIndexed { index, item ->
val isSelected = index == items.indexOf(selectedTab)
BottomNavigationItem(
icon = { Icon(if (isSelected) item.second else item.third, contentDescription = null) },
label = { Text(text = item.first) },
selected = isSelected,
onClick = {
navHostController.navigate(item.first) {
popUpTo(navHostController.graph.findStartDestination().id)
launchSingleTop = true
}
}
)
}
}
}
) {
NavHost(
navHostController,
startDestination = items[0].first,
Modifier.padding(it)
) {
composable(items[0].first) {
selectedTab = items[0]
val lifecycle = LocalLifecycleOwner.current
val viewModel: ModelDontDestory = viewModel(factory = viewModelFactory {
ModelDontDestory(lifecycle)
})
remember {
println("Recomposed first")
""
}
Text("first")
}
composable(items[1].first) {
selectedTab = items[1]
val lifecycle = LocalLifecycleOwner.current
val viewModel: ModelDontDestory = viewModel(factory = viewModelFactory {
ModelDontDestory(lifecycle)
})
remember {
println("Recomposed second")
""
}
Text("Second")
}
}
}
}
inline fun <VM : ViewModel> viewModelFactory(crossinline f: () -> VM) =
object : ViewModelProvider.Factory {
override fun <T : ViewModel> create(aClass: Class<T>): T = f() as T
}
class ModelDontDestory(val lifecycle: LifecycleOwner): ViewModel(), DefaultLifecycleObserver {
init {
lifecycle.lifecycle.addObserver(this)
}
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
println("This should never happen, this should be kept in memory")
}
}
Run Code Online (Sandbox Code Playgroud)
您已经有一个保留在内存中的对象 - ViewModel 实例本身。您不应该查看 Lifecycle 实例的销毁,因为当您的应用程序经历配置更改时也会发生这种情况。
相反,您应该查看onClearedViewModel 的方法 - 仅当实例实际从返回堆栈中删除(例如,用户离开聊天)时才会调用该方法。
同样,您不应该使用remember需要保存的状态(同样,remember变量会因多种原因而被擦除,包括当您进行配置更改时)。您应该使用rememberSaveable需要在屏幕保留在返回堆栈上的整个时间内保留的值。