简体   繁体   English

Jetpack compose NavHost 防止重新组合屏幕

[英]Jetpack compose NavHost prevent recomposition screens

as you see this is how i implemented NavHost with MaterialBottomNavigation, i have many items on both Messages and Feeds screens, when i navigate between them both screens, they automatically recomposed but i don't wanna because of much data there it flickring and fps drops to under 10 when navigating, i tried to initialize data viewModels before NavHost but still same result, is there any way to compose screens once and update them just when viewModels data updated?如您所见,这就是我使用 MaterialBottomNavigation 实现 NavHost 的方式,我在消息提要屏幕上都有很多项目,当我在它们两个屏幕之间导航时,它们会自动重新组合,但我不想因为那里有太多数据闪烁和 fps 下降导航到 10 岁以下时,我尝试在 NavHost 之前初始化数据视图模型,但结果仍然相同,有没有办法在视图模型数据更新时组合屏幕一次并更新它们?

@Composable
private fun MainScreenNavigationConfigurations(
    navController: NavHostController,
    messagesViewModel: MessagesViewModel = viewModel(),
    feedsViewModel: FeedsViewModel = viewModel(),

) {

val messages: List<Message> by messagesViewModel.messages.observeAsState(listOf())
val feeds: List<Feed> by feedsViewModel.messages.observeAsState(listOf())

NavHost(
    navController = navController,
    startDestination = "Messages"
) {
    composable("Messages") {
        Messages(navController, messages)
    }
    composable("Feeds") { Feeds(navController, feeds) }
  }
}

I had a similar problem.我有一个类似的问题。 In my case I needed to instantiate a boolean state "hasAlreadyNavigated".在我的情况下,我需要实例化一个 boolean state “hasAlreadyNavigated”。

The problem was:问题是:
-> Screen 1 should navigate to Screen 2; ->屏幕 1 应该导航到屏幕 2;
-> Screen 1 has a conditional statement for navigating directly to screen 2 or show a content screen with an action button that navigates to Screen 2; ->屏幕 1 有一个条件语句,用于直接导航到屏幕 2 或显示带有导航到屏幕 2 的操作按钮的内容屏幕;
-> After it navigates to Screen 2, Screen 1 recomposes and it reaches the if statement again, causing a "navigation loop". ->导航到屏幕 2 后,屏幕 1 重新组合并再次到达 if 语句,从而导致“导航循环”。

val hasAlreadyNavigated = remember { mutableStateOf(false) }

if (!hasAlreadyNavigated.value) {
    if (!screen1ViewModel.canNavigate()) {
        Screen1Content{
            hasAlreadyNavigated.value = true
            screen1ViewModel.allowNavigation()
            navigateToScreen2()
        }
    } else {
        hasAlreadyNavigated.value = true
        navigateToScreen2()
    }        
}

With this solution, i could prevent recomposition and the "re-navigation".使用此解决方案,我可以防止重组和“重新导航”。
I don't know if we need to be aware and build composables thinking of this recomposition after navigation or it should be library's responsibility.我不知道我们是否需要在导航后意识到并构建可组合的想法来考虑这种重组,或者这应该是图书馆的责任。

Please use this code above your code.请在您的代码上方使用此代码。 It will remember state of your current screen.它会记住您当前屏幕的 state。

val navController = rememberNavController()

for more info check this out: https://developer.android.com/jetpack/compose/navigation欲了解更多信息,请查看: https://developer.android.com/jetpack/compose/navigation

Passing the navcontroller as a parameter causes recomposition.将 navcontroller 作为参数传递会导致重新组合。 Use it as a lambda instead.将其用作 lambda 代替。

composable("Messages") {
    Messages( onClick = {navController.navigate(route = "Click1")},
              onClick2 = {navController.navigate(route = "Click2")},
              messages)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM