Android Navigation的使用说明

8.1.1 传统导航方式的痛点,以及Navigation的优势

传统导航方式的问题:

kotlin 复制代码
// 传统方式 - 使用 FragmentTransaction 手动管理导航
class MainActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 手动添加 Fragment
        supportFragmentManager.beginTransaction()
            .add(R.id.fragmentContainer, HomeFragment())
            .commit()
    }
    
    fun navigateToUserDetail(userId: String) {
        // 手动管理 Fragment 切换
        val fragment = UserDetailFragment()
        val args = Bundle()
        args.putString("userId", userId)
        fragment.arguments = args
        
        supportFragmentManager.beginTransaction()
            .replace(R.id.fragmentContainer, fragment)
            .addToBackStack("UserDetail")
            .commit()
    }
    
    fun navigateToSettings() {
        // 手动管理 Fragment 切换
        supportFragmentManager.beginTransaction()
            .replace(R.id.fragmentContainer, SettingsFragment())
            .addToBackStack("Settings")
            .commit()
    }
    
    override fun onBackPressed() {
        // 手动处理返回键
        if (supportFragmentManager.backStackEntryCount > 0) {
            supportFragmentManager.popBackStack()
        } else {
            super.onBackPressed()
        }
    }
}

传统方式的痛点:

痛点 说明 影响
代码分散 导航逻辑分散在各个地方 难以维护和理解
返回堆栈管理 需要手动管理返回堆栈 容易出现导航错误
参数传递 需要手动构建 Bundle 类型不安全
测试困难 导航逻辑与业务逻辑耦合 难以单元测试
深层链接 实现复杂 需要大量代码
kotlin 复制代码
// 使用 Navigation 组件 - 简化的导航
class MainActivity : AppCompatActivity() {
    
    private lateinit var navController: NavController
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 获取 NavController
        navController = findNavController(R.id.navHostFragment)
        
        // 设置导航图
        navController.setGraph(R.navigation.nav_graph)
    }
    
    fun navigateToUserDetail(userId: String) {
        // 类型安全的导航
        navController.navigate(
            R.id.action_homeFragment_to_userDetailFragment,
            bundleOf("userId" to userId)
        )
    }
    
    fun navigateToSettings() {
        // 简单的导航
        navController.navigate(R.id.action_homeFragment_to_settingsFragment)
    }
}

Navigation 组件的优势:

优势 说明
可视化导航 可视化的导航图,直观展示应用导航结构
类型安全 使用 Safe Args,类型安全的参数传递
自动管理返回堆栈 自动管理 Fragment 的返回堆栈
深层链接支持** 轻松实现深层链接
动画支持 内置转场动画支持
易于测试 导航逻辑与业务逻辑分离

8.2.1 导航图的基本结构

Navigation Graph XML 结构:

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/homeFragment">

    <!-- 目的地1:首页 -->
    <fragment
        android:id="@+id/homeFragment"
        android:name="com.example.app.ui.home.HomeFragment"
        android:label="Home"
        tools:layout="@layout/fragment_home">
        
        <!-- 动作:导航到用户详情页 -->
        <action
            android:id="@+id/action_homeFragment_to_userDetailFragment"
            app:destination="@id/userDetailFragment" />
        
        <!-- 动作:导航到设置页 -->
        <action
            android:id="@+id/action_homeFragment_to_settingsFragment"
            app:destination="@id/settingsFragment" />
    </fragment>

    <!-- 目的地2:用户详情页 -->
    <fragment
        android:id="@+id/userDetailFragment"
        android:name="com.example.app.ui.user.UserDetailFragment"
        android:label="User Detail"
        tools:layout="@layout/fragment_user_detail">
        
        <!-- 参数:用户 ID -->
        <argument
            android:name="userId"
            android:defaultValue=""
            app:argType="string"
            app:nullable="true" />
        
        <!-- 动作:返回首页 -->
        <action
            android:id="@+id/action_userDetailFragment_to_homeFragment"
            app:destination="@id/homeFragment"
            app:popUpTo="@id/homeFragment"
            app:popUpToInclusive="true" />
    </fragment>

    <!-- 目的地3:设置页 -->
    <fragment
        android:id="@+id/settingsFragment"
        android:name="com.example.app.ui.settings.SettingsFragment"
        android:label="Settings"
        tools:layout="@layout/fragment_settings">
        
        <!-- 动作:返回首页 -->
        <action
            android:id="@+id/action_settingsFragment_to_homeFragment"
            app:destination="@id/homeFragment"
            app:popUpTo="@id/homeFragment"
            app:popUpToInclusive="true" />
    </fragment>

</navigation>

8.2.2 目的地类型

Navigation 支持的目的地类型:

类型 说明 使用场景
Fragment Fragment 目的地 最常用的目的地类型
Activity Activity 目的地 跨 Activity 导航
Dialog Dialog 目的地 显示对话框
NavGraph 嵌套导航图 复杂的导航结构

不同目的地的示例:

xml 复制代码
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_graph"
    app:startDestination="@id/homeFragment">

    <!-- Fragment 目的地 -->
    <fragment
        android:id="@+id/homeFragment"
        android:name="com.example.app.ui.home.HomeFragment"
        android:label="Home" />

    <!-- Activity 目的地 -->
    <activity
        android:id="@+id/mainActivity"
        android:name="com.example.app.MainActivity"
        android:label="Main Activity" />

    <!-- Dialog 目的地 -->
    <dialog
        android:id="@+id/dialogFragment"
        android:name="com.example.app.ui.dialog.MyDialogFragment"
        android:label="Dialog" />

    <!-- 嵌套导航图 -->
    <include app:graph="@navigation/nested_graph" />

</navigation>

8.2.3 动作(Action)的配置

动作的属性:

xml 复制代码
<fragment
    android:id="@+id/homeFragment"
    android:name="com.example.app.ui.home.HomeFragment"
    android:label="Home">
    
    <!-- 基本动作 -->
    <action
        android:id="@+id/action_home_to_detail"
        app:destination="@id/detailFragment" />
    
    <!-- 带返回堆栈管理的动作 -->
    <action
        android:id="@+id/action_home_to_profile"
        app:destination="@id/profileFragment"
        app:popUpTo="@id/homeFragment"
        app:popUpToInclusive="true" />
    
    <!-- 带转场动画的动作 -->
    <action
        android:id="@+id/action_home_to_settings"
        app:destination="@id/settingsFragment"
        app:enterAnim="@anim/slide_in_right"
        app:exitAnim="@anim/slide_out_left"
        app:popEnterAnim="@anim/slide_in_left"
        app:popExitAnim="@anim/slide_out_right" />
    
    <!-- 单实例导航 -->
    <action
        android:id="@+id/action_home_to_login"
        app:destination="@id/loginFragment"
        app:launchSingleTop="true" />
</fragment>

相关推荐
传奇开心果编程6 小时前
【Compose Multiplatform 跨端开发学与练】第8课 资源管理与主题
android·windows·学习·ios·kotlin·web·composer
传奇开心果编程7 小时前
【Compose Multiplatform 跨端开发学与练】第9课 测试与调试
android·学习·macos·ios·kotlin·web·composer
传奇开心果编程8 小时前
【Compose Multiplatform 跨端开发学与练】第4课 导航与路由
android·windows·学习·ui·ios·kotlin·composer
传奇开心果编程8 小时前
【Compose Multiplatform 跨端开发学与练】第6课 状态管理与架构
android·学习·ui·ios·架构·kotlin·composer
事圆则缓8 小时前
Android AOSP 定制常见概念:源码目录、系统镜像与刷机流程
android
传奇开心果编程8 小时前
【Compose Multiplatform 跨端开发学与练】第2课 Compose 基础语法
android·windows·学习·ui·ios·kotlin·composer
supabc1238 小时前
Celium:连接 Windows、Mac、Linux 与 Android,让远程访问和设备管理更简单
android·linux·windows·macos·远程访问·网络管理·celium
Dovis(誓平步青云)9 小时前
导览音频切换太快,旧讲解不能覆盖新展品
android·前端·javascript·ecmascript·音视频·宠物
熊猫钓鱼>_>1 天前
Kotlin Multiplatform for OpenHarmony 实战:为 Reaktive 实现响应式原语适配(完整版 · 含摘要目录与技术图表)
华为·kotlin·大模型·ai编程·harmonyos·适配·reaktive
五彩小白1 天前
自回归和上下文
android