Navigation Patterns (导航模式)
Instructions
-
确认需求属于导览与 Back Stack 管理
-
依照下方章节顺序套用
-
一次只处理一个导航面向(Deep Link、跨模块、Back Stack)
-
完成后对照 Quick Checklist
When to Use
-
Scenario A:新项目导航设计
-
Scenario B:旧项目扩充与导航桥接
Example Prompts
-
"请参考 Type-Safe Args,更新我的 NavHost 写法"
-
"依照 Deep Links 章节,帮我加入 App Links"
-
"请用 Multi-Module Navigation 设计跨模块导航接口"
Workflow
-
先创建 Compose Navigation 基础路由
-
再加入 Deep Links 与跨模块导航
-
最后用 Back Stack 管理与 Quick Checklist 验收
Practical Notes (2026)
-
默认采用 type-safe args,避免字符串路由散落
-
Deep Link 必须有验证与回归测试流程
-
Back Stack 规则统一化,避免各模块自订逻辑
Minimal Template
目标: 路由范围: Deep Link: Back Stack 规则: 验收: Quick Checklist
Compose Navigation Basics
Type-Safe Args (Navigation 2.8+)
// 定义路由 @Serializable data class DetailRoute(val productId: String)
@Serializable object HomeRoute
// NavHost NavHost(navController, startDestination = HomeRoute) { composable<HomeRoute> { HomeScreen(onProductClick = { id -> navController.navigate(DetailRoute(id)) }) }
composable<DetailRoute> { backStackEntry ->
val route = backStackEntry.toRoute<DetailRoute>()
DetailScreen(productId = route.productId)
}
}
Nested Graphs
NavHost(navController, startDestination = "main") { navigation(startDestination = "home", route = "main") { composable("home") { HomeScreen() } composable("profile") { ProfileScreen() } }
navigation(startDestination = "login", route = "auth") {
composable("login") { LoginScreen() }
composable("register") { RegisterScreen() }
}
}
Deep Links
App Links 设置
<!-- AndroidManifest.xml --> <activity android:name=".MainActivity"> <intent-filter android:autoVerify="true"> <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="example.com" android:pathPrefix="/product" /> </intent-filter> </activity>
assetlinks.json (Host 验证)
部署位置:https://example.com/.well-known/assetlinks.json
[{ "relation": ["delegate_permission/common.handle_all_urls"], "target": { "namespace": "android_app", "package_name": "com.example.app", "sha256_cert_fingerprints": ["..."] } }]
Navigation 集成
composable( route = "product/{id}", deepLinks = listOf( navDeepLink { uriPattern = "https://example.com/product/{id}" } ) ) { backStackEntry -> val id = backStackEntry.arguments?.getString("id") ProductScreen(id) }
Multi-Module Navigation
API Module Pattern
// :feature:product:api interface ProductNavigator { fun navigateToProduct(productId: String) fun navigateToProductList() }
// :feature:product:impl class ProductNavigatorImpl @Inject constructor( private val navController: NavController ) : ProductNavigator { override fun navigateToProduct(productId: String) { navController.navigate("product/$productId") } }
// 其他模块使用 class HomeViewModel @Inject constructor( private val productNavigator: ProductNavigator ) { fun onProductClick(id: String) { productNavigator.navigateToProduct(id) } }
Navigation Events (Single Event)
// ViewModel sealed class NavigationEvent { data class ToDetail(val id: String) : NavigationEvent() object Back : NavigationEvent() }
private val _navigationEvent = Channel<NavigationEvent>() val navigationEvent = _navigationEvent.receiveAsFlow()
// Composable LaunchedEffect(Unit) { viewModel.navigationEvent.collect { event -> when (event) { is NavigationEvent.ToDetail -> navController.navigate("detail/${event.id}") NavigationEvent.Back -> navController.popBackStack() } } }
Complex Back Stack Management
Auth Flow (Clear Stack)
fun navigateToHome() { navController.navigate("home") { popUpTo("auth") { inclusive = true } // 清除 auth 流程 launchSingleTop = true } }
Bottom Nav with Separate Stacks
@Composable fun MainScreen() { val navController = rememberNavController()
Scaffold(
bottomBar = {
NavigationBar {
items.forEach { item ->
NavigationBarItem(
selected = currentRoute == item.route,
onClick = {
navController.navigate(item.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
}
)
}
}
}
) { /* NavHost */ }
}
Quick Checklist
-
使用 Type-Safe Args (Navigation 2.8+)
-
Deep Links 配置 assetlinks.json
-
跨模块使用 Navigator interface
-
Navigation Events 作为 Single Event 处理
-
Bottom Nav 正确保存/恢复 State