使用导航组件时关闭 DialogFragment 的正确方法?
Correct way to close DialogFragment when using Navigation component?
我正在使用导航组件来显示 DialogFragment
(navigation.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()
将导航到目的地的新实例,这不适合返回到您之前的实例。
我正在使用导航组件来显示 DialogFragment
(navigation.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()
将导航到目的地的新实例,这不适合返回到您之前的实例。