Android 导航组件的片段重新创建问题

问题描述 投票:0回答:1

我们的项目正在使用 jetpact 撰写和导航组件。

我们有 2 个片段 - 片段 A 和 B 。在片段 A 中,由于存在多个元素(例如 View Pager 和惰性列),UI 有点复杂。惰性列根据 viewpager 选择进行更新。从 Fragmnt A 的惰性列中选择一个项目时,它将导航到 Fragment B 。我们目前正在使用 Android 导航组件。问题是导航组件将进行片段替换。当片段 B 的 onbackpress 被调用时,它将重新创建片段 A。因此,我们会丢失片段 A 的 UI 状态。我们无法将片段 B 作为对话框目标,因为当从片段 B 打开片段 C 时,它应该位于堆栈中。

我们找到了 3 个解决方案,但都遇到了一些问题。

  1. 在 ViewModel 中保存 UI 状态并在重新创建 Fragment A 时恢复状态。

    -- 我们可以在ViewModel中保存Viewpager的UI状态。但是保存列表滚动状态将不起作用,因为列表将在 viewpager 状态更新后刷新。这种方法再次进行视图重建,这会在从片段 B 按下时造成性能延迟

  2. 将fragment Replace替换为Fragment Add后提供CustomFragmentNavigator。

    -- 这将引入更多样板代码,我们认为这是一种反模式,因为谷歌有意在导航中进行了片段替换。

  3. 在片段 A 中执行较旧的 Frgament 事务,而不是使用导航组件。当需要使用较旧的片段事务或使用导航组件添加片段时,请使用混合方法。

    -- 由于我们使用 navhostfragment ,无法获取容器 ID 来执行正常的fragment事务。我们在根布局中只有容器片段。

期待有关此问题的一些技术指导。应该用什么方法来解决这个根本问题。

android android-fragments android-jetpack-compose android-architecture-navigation android-jetpack-navigation
1个回答
0
投票

根据文档:

当您使用

popUpTo
导航到目的地时,您可以选择 保存从后堆栈弹出的所有目的地的状态

要启用此选项,请在关联操作中将

popUpToSaveState
定义为
true
,或调用
NavController.navigate()

当您导航到目的地时,您还可以将

restoreSaveState
定义为
true
,以自动恢复与目的地属性中的目的地相关联的状态

XML 示例

<action
  android:id="@+id/action_a_to_b"
  app:destination="@id/b"
  app:popUpTo="@+id/a"
  app:popUpToInclusive="true"
  app:restoreState=”true”
  app:popUpToSaveState="true"/>

撰写示例

@Composable
fun MyAppNavHost(
    modifier: Modifier = Modifier,
    navController: NavHostController = rememberNavController(),
    startDestination: String = "destination_a"
) {
    NavHost(
        modifier = modifier,
        navController = navController,
        startDestination = startDestination
    ) {
        composable("destination_a") {
            DestinationA(
                onNavigateToB = {
                // Pop everything up to the "destination_a" destination off the back stack before
                // navigating to the "destination_b" destination
                    navController.navigate("destination_b") {
                        popUpTo("destination_a") {
                            inclusive = true
                            saveState = true
                        }
                    }
                },
            )
        }
        composable("destination_b") { DestinationB(/* ... */) }
    }
}

@ Composable
fun DestinationA(onNavigateToB: () -> Unit) {
    Button(onClick = onNavigateToB) {
        Text("Go to A")
    }
}

更具体地说,您可以通过以下方式更改您的通话方式

NavController.navigate()

// Pop everything up to the destination_a destination off the back stack before
// navigating to the "destination_b" destination
navController.navigate("destination_b") {
    popUpTo("destination_a")
}

// Pop everything up to and including the "destination_a" destination off
// the back stack before navigating to the "destination_b" destination
navController.navigate("destination_b") {
    popUpTo("destination_a") { inclusive = true }
}

// Navigate to the "search” destination only if we’re not already on
// the "search" destination, avoiding multiple copies on the top of the
// back stack
navController.navigate("search") {
    launchSingleTop = true
}

请参阅此链接了解更多信息: 导航和返回堆栈

© www.soinside.com 2019 - 2024. All rights reserved.