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

Jetpack Compose导航Deep Link导致重复Activity问题求助

解决点击通知打开ChatScreen时重复创建MainActivity的问题

问题根源

你遇到的核心问题在于:TaskStackBuilder.addNextIntentWithParentStack会自动构建包含父Activity的返回栈,加上启动模式配置与DeepLink处理的配合不当,导致每次点击通知都新建MainActivity实例。以下是针对性的解决方案:


1. 修正Manifest配置

将MainActivity的启动模式从singleInstance改为singleTop(singleInstance会将Activity单独隔离在任务栈,反而容易导致栈混乱),并拆分DeepLink的Intent过滤器,避免与启动入口冲突:

<application
    <!-- 其他配置保持不变 -->
    >
    <activity
        android:name=".features.MainActivity"
        android:launchMode="singleTop" <!-- 修改为singleTop -->
        android:exported="true"
        android:theme="@style/Theme.Mantools.Splash">
        <!-- 启动入口过滤器 -->
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <!-- 单独的DeepLink过滤器 -->
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="https" android:host="mantools" android:path="/chats"/>
        </intent-filter>
    </activity>
</application>

2. 优化通知Intent与PendingIntent构建

去掉TaskStackBuilder的冗余栈构建,直接使用带明确Flags的Intent,确保复用已存在的MainActivity:

private fun showChatNotification(message: RemoteMessage) {
    val data = message.data
    val deepLinkUri = "https://mantools/chats".toUri()
    // 使用ACTION_VIEW而非ACTION_MAIN,符合DeepLink标准用法
    val intent = Intent(Intent.ACTION_VIEW, deepLinkUri).apply {
        setPackage(context.packageName) // 限定仅当前App响应
        flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or 
                Intent.FLAG_ACTIVITY_SINGLE_TOP or 
                Intent.FLAG_ACTIVITY_NEW_TASK
    }
    showNotification(
        data["title"] ?: "",
        data["text"] ?: "",
        TAG_CHAT,
        intent
    )
}

// 简化PendingIntent构建,无需TaskStackBuilder
private fun getPendingIntent(intent: Intent) = PendingIntent.getActivity(
    context,
    0, // 若需区分不同通知,可传入唯一requestCode
    intent,
    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)

在MainActivity中重写onNewIntent方法,让Compose Destinations处理DeepLink导航(singleTop模式下,已存在的Activity会触发此方法而非onCreate):

class MainActivity : ComponentActivity() {
    private lateinit var navController: NavController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MantoolsTheme {
                navController = rememberNavController()
                DestinationsNavHost(
                    navController = navController,
                    navGraph = NavGraphs.root
                )
            }
        }
        // 处理启动时的DeepLink
        intent?.let { handleDeepLink(it) }
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        // 处理通知触发的DeepLink
        intent?.let { handleDeepLink(it) }
    }

    private fun handleDeepLink(intent: Intent) {
        intent.data?.let { uri ->
            navController.navigate(uri)
        }
    }
}

关键说明

  • singleTop模式:确保当MainActivity处于栈顶时,不会新建实例,而是调用onNewIntent复用现有实例。
  • Intent Flags:
    • FLAG_ACTIVITY_CLEAR_TOP:清除MainActivity之上的所有Activity,保证返回栈简洁。
    • FLAG_ACTIVITY_SINGLE_TOP:强制复用栈顶的MainActivity。
    • FLAG_ACTIVITY_NEW_TASK:确保App在后台时能正确启动任务栈。
  • 去掉TaskStackBuilder:避免自动添加冗余的父栈元素,直接通过DeepLink让Compose Destinations完成导航逻辑。

内容的提问来源于stack exchange,提问作者Risal Fajar Amiyardi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 10:51:11