使用 bottomsheet 的操作打开另一个 dialogfragment 而不会崩溃 android 导航组件

Use bottomsheet's action to open another dialogfragment without crashing android navigation component

我有 Fragment A、BottomSheetDialogFragment B 和 DialogFragment C。我希望能够从 B 选择一个动作,关闭 B 返回 A,然后使用导航实时数据从 A 导航到 C。

A 和 B 共享相同的 activityViewModel。我的意图是,当单击 B 中的操作按钮时,它将关闭 B,修改 activityViewModel 中的标志,A 将观察标志的变化并随后打开 C。但是,我收到一个错误,我认为它认为我正在从 B 导航到 C(而不是 A 到 C):

java.lang.IllegalArgumentException: 导航目的地...action_FragmentA_to_DialogFragmentC 对此 NavController

未知

我认为异常是由于程序认为操作是从 B 到 C。

class DetailBottomSheet : BottomSheetDialogFragment() {

    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory
    private val detailViewModel by activityViewModels<DetailViewModel>() { viewModelFactory }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        binding.bottomSheetAction.setOnClickListener {
            dismiss()
            detailViewModel.setBottomSheetDialogType(1)
        }
    }
}

class DetailFragment : Fragment() {

    @Inject
    lateinit var viewModelFactory: ViewModelProvider.Factory
    private val detailViewModel by activityViewModels<DetailViewModel>() { viewModelFactory }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        detailViewModel.bottomSheetDialogType.observe(viewLifecycleOwner, Observer {
            when (it) {
                1 -> detailViewModel.navigateToDialogFragmentC(args.id)
                else -> {}
            }
        })

        detailViewModel.navigateToDialogFragmentC.observe(
            viewLifecycleOwner,
            WrapperEventObserver {
                Thread.sleep(500) // thought this would allow wait time for bottomsheet to dismiss, but doesn't make a difference
                val action =
                    DetailFragmentDirections.actionFragmentAToDialogFragmentC(it)
                findNavController().navigate(action)
            })
    }
}

在这种情况下,我可以使用哪些修复程序来正确导航?

在任何 DialogFragment 上调用 dismiss() 异步更新 NavController 状态 - 这意味着从 NavController 的角度来看,您 当你的 bottomSheetDialogType 侦测器开火时仍然在 DetailBottomSheet

您应该改用 findNavController().popBackStack(),它将同步更新 NavController 的状态(有效地将您移回 A)并调用 dismiss() 本身来隐藏底部 sheet对话框。

binding.bottomSheetAction.setOnClickListener {
    findNavController().popBackStack()
    detailViewModel.setBottomSheetDialogType(1)
}