首页 > 解决方案 > Correct way to close DialogFragment when using Navigation component?

问题描述

I am using the Navigation component to show a DialogFragment (<dialog...>...</dialog> in the navigation.xml) and want to know what's the recommended way to close the Dialog. I tried myself and got the following results:

1) dismiss()in DialogFragment: seems to work fine

2) findNavController().navigateUp(): seems to work fine

3) findNavController().navigate(MyDialogFragmentDirections.actionMyDialogFragmentToMyNormalFragment()): works, but loads a fresh version of the target destination, so depending on the use case this might not be what one wants to have.

Note: My use case is that MyNormalFragmentuses MyDialogFragmentto get some input, so after MyDialogFragmentis shown, I need to get back to the already existing instance of MyNormalFragment.

So for me, only 1) or 2) is correct. Now I am wondering, is there any difference between 1) and 2) ?

标签: androidnavigationandroid-architecture-components

解决方案


1) 和 2) 最终都会做同样的事情,但 2) 始终是更安全的选择。

当您调用 时dismiss(),将DialogFragment关闭并DialogFragment停止 (它会收到对 的回调onStop())。这会触发监听DialogFragmentNavigator器,然后NavController通过调用更新 的状态popBackStack()

dismiss()但是,它是一个异步操作(如DialogFragment源代码中所示- 您会注意到它不使用commitNow()等)。因此,如果您要从 中检查您所在的目的地NavController.getCurrentDestination(),您会看到您仍在对话目的地上,尽管已触发解雇。

navigateUp(),另一方面,直接进入 NavController。由于您的后堆栈上有另一个目的地(在 下的那个DialogFragment),NavController源代码显示navigateUp()只是调用-最终触发popBackStack()的操作相同。dismiss()

但是,当它NavController是驱动操作时,会NavController同步更新其状态。这意味着,在您调用 之后navigateUp(),它会立即更新其getCurrentDestination()内部状态,此外还会调用 to DialogFragmentNavigatorpopBackStack()这就是调用 to dismiss()(删除上面提到的观察者以防止双重解雇)。

因此调用navigateUp()始终是更安全的选择,因为它可以确保NavController同步更新到正确的状态,而不是依赖于FragmentManager的异步计时(这可能意味着在该时间段内由于多点触控等原因会收到额外的点击事件。 )。

navigate()使用带有 on 的操作调用app:destination将导航到目标的新实例,这不适合返回到之前的实例。


推荐阅读