【问题标题】:Jetpack Compose Navigation - Bottom Nav Multiple Back Stack - View Model Scoping IssueJetpack Compose Navigation - 底部导航多个返回堆栈 - 查看模型范围问题
【发布时间】:2021-11-24 03:01:11
【问题描述】:

所以我有两个选项卡,选项卡 A 和选项卡 B。每个选项卡都有自己的后退堆栈。我使用google docs中的代码实现了多回栈导航

    val navController = rememberNavController()
Scaffold(
  bottomBar = {
    BottomNavigation {
      val navBackStackEntry by navController.currentBackStackEntryAsState()
      val currentDestination = navBackStackEntry?.destination
      items.forEach { screen ->
        BottomNavigationItem(
          icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
          label = { Text(stringResource(screen.resourceId)) },
          selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
          onClick = {
            navController.navigate(screen.route) {
              // Pop up to the start destination of the graph to
              // avoid building up a large stack of destinations
              // on the back stack as users select items
              popUpTo(navController.graph.findStartDestination().id) {
                saveState = true
              }
              // Avoid multiple copies of the same destination when
              // reselecting the same item
              launchSingleTop = true
              // Restore state when reselecting a previously selected item
              restoreState = true
            }
          }
        )
      }
    }
  }
) { 
  NavHost(navController, startDestination = A1.route) {
    composable(A1.route) { 
       val viewModelA1 = hiltViewModel() 
       A1(viewModelA1) 
    }
    composable(A2.route) { 
       val viewModelA2 = hiltViewModel() 
       A2(viewModelA2) 
    }
    composable(A3.route) { 
       val viewModelA3 = hiltViewModel() 
       A3(viewModelA3) 
    }
  }
}

选项卡 A 有 3 个屏幕(屏幕 A1 -> 屏幕 A2 -> 屏幕 A3)。我使用hiltViewModel() 函数来实例化视图模型,并在每个屏幕的composable() 块中调用它

问题是当我从 A1 导航到 A2 再到 A3 时,然后当我将选项卡更改为选项卡 B 时,屏幕 A2 的视图模型似乎正在被处理(调用onCleared)。因此,当我返回显示屏幕 A3 的选项卡 A 然后返回屏幕 A2 时,再次实例化 A2 的视图模型(再次调用 init 块)。我想要实现的是为这个流程保留 A2 的视图模型,直到我退出 A2。

这可能吗?

【问题讨论】:

    标签: android kotlin android-jetpack-compose android-jetpack-navigation jetpack-compose-navigation


    【解决方案1】:

    当您点击下一个导航项的速度过快,而当前视图显示转换尚未完成时,这似乎是一个错误。我已经reported了,请star一下,引起更多关注。

    同时,您可以等待当前屏幕转换完成,然后再导航到下一个屏幕。为此,您可以检查 visibleEntries 变量并仅在它仅包含单个项目后导航。

    另外,我认为当前文档提供的底部导航并不是最好的示例,因为如果您不在起始目的地屏幕上,按下后退按钮会将您带回到起始目的地,而我预计视图会被关闭.所以我也改变了你的导航方式,如果你对文档行为没问题,你可以用你自己的替换 fun navigate() 的内容。

    val navController = rememberNavController()
    var waitEndAnimationJob by remember { mutableStateOf<Job?>(null)}
    Scaffold(
        bottomBar = {
            BottomNavigation {
                val navBackStackEntry by navController.currentBackStackEntryAsState()
                val currentDestination = navBackStackEntry?.destination
                val scope = rememberCoroutineScope()
                items.forEach { screen ->
                    fun navigate() {
                        navController.navigate(screen.route) {
                            val navigationRoutes = items
                                .map(Screen::route)
                            val firstBottomBarDestination = navController.backQueue
                                .firstOrNull { navigationRoutes.contains(it.destination.route) }
                                ?.destination
                            // remove all navigation items from the stack
                            // so only the currently selected screen remains in the stack
                            if (firstBottomBarDestination != null) {
                                popUpTo(firstBottomBarDestination.id) {
                                    inclusive = true
                                    saveState = true
                                }
                            }
                            // Avoid multiple copies of the same destination when
                            // reselecting the same item
                            launchSingleTop = true
                            // Restore state when reselecting a previously selected item
                            restoreState = true
                        }
                    }
                    BottomNavigationItem(
                        icon = { Icon(Icons.Filled.Favorite, contentDescription = null) },
                        label = { Text(stringResource(screen.resourceId)) },
                        selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
                        onClick = {
                            // if we're already waiting for an other screen to start appearing
                            // we need to cancel that job   
                            waitEndAnimationJob?.cancel()
                            if (navController.visibleEntries.value.count() > 1) {
                                // if navController.visibleEntries has more than one item
                                // we need to wait animation to finish before starting next navigation
                                waitEndAnimationJob = scope.launch {
                                    navController.visibleEntries
                                        .collect { visibleEntries ->
                                            if (visibleEntries.count() == 1) {
                                                navigate()
                                                waitEndAnimationJob = null
                                                cancel()
                                            }
                                        }
                                }
                            } else {
                                // otherwise we can navigate instantly
                                navigate()
                            }
                        }
                    )
                }
            }
        }
    ) { innerPadding ->
        // ...
    }
    

    【讨论】:

      【解决方案2】:

      找到了这个问题的根本原因。我正在使用这些依赖项,但它们似乎并没有结合在一起。

      androidx.hilt:hilt-navigation-compose:1.0.0-alpha03 
      
      androidx.navigation:navigation-compose:2.4.0-alpha10" 
      

      我删除了 navigation:navigation-compose 依赖项,现在它似乎可以正常工作了。

      【讨论】:

        猜你喜欢
        • 2023-02-21
        • 2023-03-03
        • 2022-07-22
        • 1970-01-01
        • 1970-01-01
        • 2013-07-02
        • 1970-01-01
        • 1970-01-01
        • 2021-10-13
        相关资源
        最近更新 更多