使用导航组件时关闭 DialogFragment 的正确方法?

Correct way to close DialogFragment when using Navigation component?

我正在使用导航组件来显示 DialogFragmentnavigation.xml 中的 <dialog...>...</dialog>),我想知道关闭对话框的推荐方法是什么。我自己试了一下,结果如下:

1) dismiss()DialogFragment 中:似乎工作正常

2) findNavController().navigateUp(): 似乎工作正常

3) findNavController().navigate(MyDialogFragmentDirections.actionMyDialogFragmentToMyNormalFragment()):有效,但会加载目标目的地的新版本,因此根据用例,这可能不是人们想要的。

注意:我的用例是 MyNormalFragment 使用 MyDialogFragment 来获取一些输入,因此在显示 MyDialogFragment 之后,我需要返回到已经存在的 MyNormalFragment.

所以对我来说,只有 1) 或 2) 是正确的。现在我想知道,1) 和 2) 之间有什么区别吗?

1) 和 2) 最后都会做同样的事情,但是 2) 总是一个更安全的选择。

当您调用 dismiss() 时,DialogFragment 被取消并且 DialogFragment 停止(它接收到 onStop() 的回调)。这会触发 listener in DialogFragmentNavigator,然后通过调用 popBackStack().

更新 NavController 的状态 然而,

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

另一方面,

navigateUp() 直接转到 NavController。由于您的返回堆栈上有另一个目的地(DialogFragment 下的目的地),NavController source code 显示 navigateUp() 只是调用 popBackStack() - 与 [=10= 相同的操作] 最终触发。

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

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

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