跳转到正文
YGJoon
返回

Android Kotlin Compose 导航与深链

编辑文章

路由设计

sealed class Destinations(val route: String) {
    data object Home : Destinations("home")
    data object Detail : Destinations("detail/{id}") {
        fun createRoute(id: Long) = "detail/$id"
    }
}

基础导航

@Composable
fun AppNavGraph(navController: NavHostController = rememberNavController()) {
    NavHost(navController, startDestination = Destinations.Home.route) {
        composable(Destinations.Home.route) {
            HomeRoute(onOpenDetail = { id ->
                navController.navigate(Destinations.Detail.createRoute(id))
            })
        }
        composable(
            Destinations.Detail.route,
            arguments = listOf(navArgument("id") { type = NavType.LongType })
        ) { entry ->
            val id = entry.arguments?.getLong("id") ?: return@composable
            DetailRoute(id)
        }
    }
}

多返回栈与 BottomBar

val tabs = listOf("feed", "search", "profile")
val navController = rememberNavController()

NavigationBar {
    tabs.forEach { tab ->
        NavigationBarItem(
            selected = navController.currentDestination?.route == tab,
            onClick = {
                navController.navigate(tab) {
                    popUpTo(navController.graph.startDestinationId) { saveState = true }
                    launchSingleTop = true
                    restoreState = true
                }
            },
            icon = { Icon(Icons.Default.Home, null) },
            label = { Text(tab) }
        )
    }
}

深链与外部跳转

Manifest 配置

<activity
    android:name=".MainActivity"
    android:exported="true">
    <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="app" android:host="example" android:pathPrefix="/detail" />
    </intent-filter>
</activity>

Compose 处理

@Composable
fun MainApp(navController: NavHostController = rememberNavController()) {
    val intent = LocalContext.current.findActivity()?.intent
    LaunchedEffect(intent) {
        intent?.data?.lastPathSegment?.toLongOrNull()?.let { id ->
            navController.navigate(Destinations.Detail.createRoute(id))
        }
    }
    AppNavGraph(navController)
}

多模块导航

interface NavigationDestination {
    val route: String
    fun register(navGraphBuilder: NavGraphBuilder, navController: NavController)
}

class ProfileDestination @Inject constructor(): NavigationDestination {
    override val route = "profile"
    override fun register(navGraphBuilder: NavGraphBuilder, navController: NavController) {
        navGraphBuilder.composable(route) { ProfileRoute() }
    }
}

内存与状态保存

navController.currentBackStackEntry?.savedStateHandle?.set("result", result)
navController.popBackStack()

val result = navController.currentBackStackEntry?.savedStateHandle?.getStateFlow("result", null)

常见问题

问题原因解决方案
返回栈错乱未设置 launchSingleTop在 navigate 中配置 launchSingleTop
参数解析失败参数类型不匹配使用 navArgument 指定类型
多模块冲突路由名称重复采用命名空间前缀或封装 Destination 类

总结

  1. Compose Navigation 提供声明式路由配置,配合 sealed class 管理更清晰。
  2. 深链需同时配置 Manifest 与导航逻辑,确保参数安全解析。
  3. 在多模块项目中抽象导航接口,避免直接引用具体实现,使路由体系可扩展、可维护。

编辑文章
分享这篇文章:

上一篇
Android Kotlin DataStore 配置与迁移
下一篇
Android Kotlin Compose 可访问性与无障碍