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>

相关推荐
高林雨露2 小时前
Java开发转kotlin
java·kotlin
JJay.2 小时前
高通 GAIA v1/v2/v3 共存时,Android 端该怎么做协议分层
android
哑巴湖小水怪11 小时前
Android的架构是四层还是五层
android·架构
2501_9160088913 小时前
深入解析iOS应用启动性能优化策略与实践
android·ios·性能优化·小程序·uni-app·cocoa·iphone
美狐美颜SDK开放平台15 小时前
短视频/直播双场景美颜SDK开发方案:接入、功能、架构详解
android·ios·美颜sdk·第三方美颜sdk·视频美颜sdk
untE EADO15 小时前
在 MySQL 中使用 `REPLACE` 函数
android·数据库·mysql
iblade15 小时前
Android CLI And Skills 3x faster
android
阿巴斯甜17 小时前
SharedUnPeekLiveData和UnPeekBus的区别:
android
阿巴斯甜17 小时前
UnPeek-LiveData的使用:
android