You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose二级页面导航栈异常问题求助

Deep Link代理页面导致二级页面导航栈异常修复

问题场景

为第三方OAuth回调实现了Deep Link代理页面,触发认证前保存当前页面路由,回调后读取路由导航回原页面。一级页面逻辑正常,但二级页面(如路由account/Settings)成功导航后,点击返回无法回到父页面(账户页),而是停留在当前二级页面。

问题根源

  1. 导航回目标页面时默认将页面添加到栈中,栈结构变为:账户页 → 代理页 → 设置页。返回时先回到代理页,代理页又重新导航到设置页,形成循环。
  2. 存储的路由值未及时清理,代理页每次进入都会读取旧路由重复导航。
  3. LaunchedEffect(true)会在Composable重组时重复执行,触发多次导航。

修复方案

1. 导航时清理代理页栈

修改导航逻辑,用popUpTo移除栈中的代理页,避免返回循环:

// 在addProxy函数中修改goBack和goOnSuccess的实现
goBack = oldBackRoute?.let { backRoute ->
    {
        navController.navigate(backRoute) {
            // 从栈中移除代理页,inclusive=true表示同时移除当前代理页
            popUpTo(LeafScreen.Account.Proxy.createRoute(root)) { inclusive = true }
        }
    }
},
goOnSuccess = oldLoggedInRoute?.let { successRoute ->
    {
        navController.navigate(successRoute) {
            popUpTo(LeafScreen.Account.Proxy.createRoute(root)) { inclusive = true }
            // 确保目标页面只存在一个实例
            launchSingleTop = true
        }
    }
},

2. 读取存储路由后立即清理

读取backRoute和loggedInRoute后,立即清理存储,避免下次进入代理页重复使用旧值:

if (!oldBackRoute.isNullOrBlank()) {
    it.arguments!!.putString("backRoute", oldBackRoute)
    // 清理存储的路由值
    clearValueFromStorage("backRoute")
}
if (!oldLoggedInRoute.isNullOrBlank()) {
    it.arguments!!.putString("loggedInRoute", oldLoggedInRoute)
    clearValueFromStorage("loggedInRoute")
}

3. 确保LaunchedEffect仅执行一次

将LaunchedEffect的key改为code,避免重组时重复触发导航:

@Composable
fun ProxyScreen(
    logViewModel: LogViewModel,
    deeplinkViewModel: DeeplinkViewModel,
    goBack: (() -> Unit)? = null,
    goOnSuccess: (() -> Unit)? = null,
    intentData: Bundle?
) {
    val code = intentData?.getString("code")
    LaunchedEffect(code) {
        delay(500)
        sharedIntentData = intentData
        if (!code.isNullOrBlank() && goOnSuccess != null) {
            goOnSuccess()
        } else {
            goBack?.invoke()
        }
    }

    // 原有UI代码不变
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
    ) {
        Box(
            modifier = Modifier.fillMaxSize(),
            contentAlignment = Alignment.Center,
        ) {
            LoadingCircle()
        }
    }
}

4. 避免修改Composable的arguments

直接使用读取到的oldBackRoute和oldLoggedInRoute构建导航回调,无需修改arguments,减少意外重组:

// 替换addProxy中的相关逻辑
val oldBackRoute = if (!code.isNullOrBlank()) loadValueFromStorage("backRoute") else null
val oldLoggedInRoute = if (!code.isNullOrBlank()) loadValueFromStorage("loggedInRoute") else null

ProxyScreen(
    logViewModel = logViewModel,
    deeplinkViewModel = deeplinkViewModel,
    goBack = oldBackRoute?.let { backRoute ->
        {
            navController.navigate(backRoute) {
                popUpTo(LeafScreen.Account.Proxy.createRoute(root)) { inclusive = true }
            }
        }
    },
    goOnSuccess = oldLoggedInRoute?.let { successRoute ->
        {
            navController.navigate(successRoute) {
                popUpTo(LeafScreen.Account.Proxy.createRoute(root)) { inclusive = true }
                launchSingleTop = true
            }
        }
    },
    intentData = it.arguments
)

内容的提问来源于stack exchange,提问作者Bastian Noffer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 10:50:41