Navigation Fragment<include>覆盖startDestination值问题求助
问题描述
在多模块Android应用中使用Navigation Component,:app模块的主导航图通过<include>导入了:features:transfer模块的子导航图,但运行时主导航图设置的startDestination="@id/mainFragment"被替换成了子导航图的startDestination="@id/transferRecipientFragment"。
主导航图代码:
<?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/main_navigation" app:startDestination="@id/mainFragment"> <include app:graph="@navigation/nav_transfer" /> <fragment android:id="@+id/mainFragment" android:name="com.fanjavaid.navigationcomponent.fragments.MainFragment" android:label="Home" tools:layout="@layout/fragment_main"> <action android:id="@+id/action_mainFragment_to_transferNavigationGraph" app:destination="@id/transferNavigationGraph" /> <action android:id="@+id/action_mainFragment_to_balanceFragment" app:destination="@id/balanceFragment" /> </fragment> <fragment android:id="@+id/balanceFragment" android:name="com.fanjavaid.navigationcomponent.fragments.BalanceFragment" android:label="View Balance" tools:layout="@layout/fragment_balance" /> <action android:id="@+id/action_global_to_mainFragment" app:destination="@id/mainFragment" app:popUpTo="@id/mainFragment" app:popUpToInclusive="true" /> </navigation>
子导航图代码:
<?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/transferNavigationGraph" app:startDestination="@id/transferRecipientFragment"> <fragment android:id="@+id/transferRecipientFragment" android:name="com.fanjavaid.transfer.fragments.TransferRecipientFragment" android:label="Transfer Recipient" tools:layout="@layout/fragment_transfer_recipient"> <action android:id="@+id/action_transferRecipientFragment_to_transferAmountFragment" app:destination="@id/transferAmountFragment" /> </fragment> <fragment android:id="@+id/transferAmountFragment" android:name="com.fanjavaid.transfer.fragments.TransferAmountFragment" android:label="Transfer Amount" tools:layout="@layout/fragment_transfer_amount"> <argument android:name="recipient" app:argType="com.fanjavaid.data.models.Recipient" /> </fragment> </navigation>
原因分析
直接使用<include>导入子导航图时,Navigation Component会将子图的所有配置(包括startDestination)直接合并到主导航图中。由于合并优先级的规则,子图的startDestination会覆盖主图的对应配置,导致启动页被替换。
解决方案
方法1:将子导航图改为嵌套导航结构
把主导航图中的直接<include>替换为嵌套导航节点,这样子图的配置会被封装在独立的导航节点内,不会影响主图的启动页设置:
修改主导航图中的<include>部分为:
<navigation android:id="@+id/transferNavigationGraph" app:startDestination="@id/transferRecipientFragment"> <include app:graph="@navigation/nav_transfer" /> </navigation>
同时可以删除子导航图中的app:startDestination="@id/transferRecipientFragment"(保留也不会影响主图,因为嵌套节点已明确启动页)。
方法2:移除子导航图的startDestination属性
直接删除子导航图中的app:startDestination配置,让主导航图完全控制启动逻辑。此时主图的startDestination不会被覆盖,你依然可以通过主图中定义的action_mainFragment_to_transferNavigationGraph跳转到子图的第一个页面(Navigation会默认导航到子图的第一个目的地)。
修改后的子导航图:
<?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/transferNavigationGraph"> <fragment android:id="@+id/transferRecipientFragment" android:name="com.fanjavaid.transfer.fragments.TransferRecipientFragment" android:label="Transfer Recipient" tools:layout="@layout/fragment_transfer_recipient"> <action android:id="@+id/action_transferRecipientFragment_to_transferAmountFragment" app:destination="@id/transferAmountFragment" /> </fragment> <fragment android:id="@+id/transferAmountFragment" android:name="com.fanjavaid.transfer.fragments.TransferAmountFragment" android:label="Transfer Amount" tools:layout="@layout/fragment_transfer_amount"> <argument android:name="recipient" app:argType="com.fanjavaid.data.models.Recipient" /> </fragment> </navigation>
内容的提问来源于stack exchange,提问作者fanjavaid

