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

Navigation Graph技术咨询:通用错误页、数据回调及跨导航跳转

1. 实现通用错误页面,消除重复定义

当前每个嵌套导航图都单独添加错误Fragment,导致重复代码冗余。解决方案是将错误Fragment统一放在主导航图中,所有子导航图直接复用,无需重复定义。

步骤:

  • 在main_navigation.xml中添加通用错误页的定义,移除各子导航图中的错误Fragment代码:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_navigation"
    app:startDestination="@+id/home_navigation">

    <!-- 原有嵌套导航图 -->
    <include app:graph="@navigation/home_navigation" />
    <include app:graph="@navigation/explorer_navigation" />
    <include app:graph="@navigation/favourite_navigation" />
    <include app:graph="@navigation/server_navigation" />
    <include app:graph="@navigation/settings_navigation" />

    <!-- 全局通用错误页 -->
    <fragment
        android:id="@+id/fragment_error"
        android:name="com.xyz.android.ui.nodata.ErrorBaseFragment">
        <argument
            android:name="title"
            android:defaultValue="NO_DATA"
            app:argType="string" />
        <argument
            android:name="errorType"
            app:argType="com.xyz.android.ui.nodata.EnumErrorType"
            android:defaultValue="NO_DATA" />
        <!-- 可选:自定义操作按钮文本 -->
        <argument
            android:name="actionText"
            android:defaultValue="RETRY"
            app:argType="string" />
    </fragment>
</navigation>
  • 在任意子导航图的页面中,直接通过ID跳转至通用错误页,无需在子图中定义action:
// 示例:在SettingsBaseFragment中跳转错误页
val errorArgs = ErrorBaseFragmentArgs.Builder()
    .setTitle(getString(R.string.error_network_title))
    .setErrorType(EnumErrorType.NETWORK_ERROR)
    .setActionText(getString(R.string.btn_retry))
    .build()
findNavController().navigate(R.id.fragment_error, errorArgs.toBundle())

2. 错误页点击按钮携带数据回调前一页

利用Navigation的SavedStateHandle返回结果API(2.3.0+版本支持),无需额外接口或ViewModel,直接实现数据回调。

步骤:

  • 在跳转前的页面(如SettingsBaseFragment)注册结果监听:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    // 监听错误页返回的操作结果
    findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<Boolean>("isRetry")?.observe(viewLifecycleOwner) { isRetry ->
        if (isRetry) {
            // 执行对应逻辑,比如重新加载数据
            loadSettingsData()
        }
    }
}
  • 在错误页ErrorBaseFragment的按钮点击事件中,传递数据并返回:
binding.btnAction.setOnClickListener {
    // 传递返回数据(支持布尔、字符串、Parcelable等类型)
    findNavController().previousBackStackEntry?.savedStateHandle?.set("isRetry", true)
    // 返回上一页
    findNavController().popBackStack()
}

如果需要传递复杂自定义对象,确保对象实现Parcelable或Serializable接口。

3. 子导航向父导航跳转其他目标(替代共享ViewModel)

推荐使用全局Action或直接导航目标ID,比共享ViewModel更简洁直接。

方案一:全局Action(推荐)

在主导航图中定义全局Action,指向目标页面,子导航图的页面可直接调用:

<!-- 在main_navigation.xml中添加全局跳转Action -->
<action
    android:id="@+id/action_global_home_fragment"
    app:destination="@id/home_fragment" /> <!-- home_fragment是home_navigation中的目标ID -->

在子导航图的页面中调用:

// 示例:从Settings相关页面跳转到首页
findNavController().navigate(R.id.action_global_home_fragment)

方案二:直接导航目标ID

如果目标页面的ID在主导航图中可访问(包括子导航图内的目标),直接用ID跳转,Navigation会自动处理跨子图导航:

// 直接跳转到home_navigation的首页
findNavController().navigate(R.id.home_fragment)
// 或直接跳转到整个home导航图(回到首页栈顶)
findNavController().navigate(R.id.home_navigation)

内容的提问来源于stack exchange,提问作者Sneha Bansal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 05:08:08