Navigation组件实现DialogFragment间相互跳转方法
跳转失效根因
- 跳转前手动调用
dismiss()会直接销毁当前FirstDialog实例,导致其脱离NavController绑定的导航栈,后续的navigate指令找不到有效导航宿主,自然无法弹出第二个对话框。 - 现有导航图存在配置错误:SecondDialog下定义的返回action目标地址写为自身(
app:destination="@+id/dialog_second"),属于笔误,即使触发也无法回到第一个对话框。
正确实现步骤
- 第一步:修正导航图配置
不需要为两个对话框配置双向跳转action,利用Navigation自带的返回栈能力即可实现来回切换,修正后的配置如下:
<dialog android:id="@+id/dialog_first" android:name="com.example.dialog.FirstDialog" android:label="first" tools:layout="@layout/myfirstdialog"> <argument android:name="phonenumber" app:argType="string"/> <action android:id="@+id/action_dialog_first_to_dialog_second" app:destination="@+id/dialog_second" app:popUpTo="@id/dialog_first" app:popUpToInclusive="false"/> </dialog> <dialog android:id="@+id/dialog_second" android:name="com.example.dialog.SecondDialog" android:label="second" tools:layout="@layout/myseconddialog"> <!-- 无需额外配置跳回FirstDialog的action --> </dialog>
配置中popUpTo相关属性的作用是导航到SecondDialog时,保证FirstDialog始终留在返回栈中,不会因为栈复用被意外销毁。
- 第二步:修改FirstDialog跳转逻辑
删除手动调用的dismiss()方法,Navigation组件会自动管理栈内DialogFragment的显示/隐藏状态,手动dismiss会破坏导航栈的一致性。正确跳转代码:
btnGoToSecondDialog.setOnClickListener{ findNavController().navigate( FirstDialogDirections.actionDialogFirstToDialogSecond() ) }
- 第三步:实现SecondDialog返回逻辑
不需要自定义跳转action,直接调用导航组件的返回方法即可,系统会自动弹出栈顶的SecondDialog,展示栈内留存的FirstDialog:
btnBackToFirstDialog.setOnClickListener{ findNavController().navigateUp() }
参数保留问题说明
完全不需要在两个对话框之间来回透传phonenumber参数。按照上述配置,从FirstDialog跳转到SecondDialog时,FirstDialog实例会一直保存在导航返回栈中,不会被销毁重建,其初始化时接收的phonenumber参数会一直存在于实例内存中。从SecondDialog返回时直接复用原有FirstDialog实例,参数可直接正常读取,不存在丢失问题。
只有当配置popUpToInclusive="true"将FirstDialog主动弹出返回栈、返回时需要重新创建FirstDialog实例的场景,才需要将参数透传到SecondDialog,返回时再通过SavedStateHandle或Bundle回传。
注意:使用Navigation 2.4.0及以上版本时,DialogFragment目的地的栈管理逻辑已经过优化,只要不手动调用dismiss、不主动将前序Dialog弹出栈,实例及其绑定的参数都会自动留存。
内容的提问来源于stack exchange,提问作者HeraGonz
相关产品推荐
相关产品推荐

