【问题标题】:Navigating from BottomSheetFragment with Jetpack Navigation results with crash 'Action can not be found from current destination'从带有 Jetpack 导航结果的 BottomSheetFragment 导航,出现崩溃“无法从当前目的地找到操作”
【发布时间】:2021-10-15 14:20:51
【问题描述】:

这个案例可能是一个独特的案例,因为我确实有一些复杂的导航逻辑,并且我正在使用扩展功能(我将在下面分享)。

  • 想象有一个 Fragment(A) 打开一个 BottomSheetFragment(B)
  • BottomSheetFragment(B) 里面有一个按钮。
  • 点击按钮会关闭 BottomSheetFragment(B) 并导航到新的 Fragment(C)。

为了处理这种情况,我使用了 2 个扩展函数:

fun <T> Fragment.setNavigationResult(key: String, result: T) {
    findNavController().previousBackStackEntry?.savedStateHandle?.set(key, result)
}

fun <T> Fragment.getNavigationResult(key: String) = findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<T>(key)

在BottomSheetFragment(B)中实现setNavigationResult

loginButton.setOnClickListener {
            dismiss()
            setNavigationResult(EVENT_CUSTOMER_SIGNUP_LOGIN, Event(true))
        }

在 Fragment(A) 中实现getNavigationResult

getNavigationResult<Event<Boolean>>(EVENT_CUSTOMER_SIGNUP_LOGIN)?.observe(viewLifecycleOwner) { event ->
            event.value?.let {
                findNavController().navigate(R.id.openCustomerLogin)
            }
        }

应用程序崩溃并出现以下错误:

    java.lang.IllegalArgumentException: Navigation action/destination openFragmentC cannot be found from the current destination Destination(FragmentB)

这里我不明白的是,即使我之前打电话给dismiss,当前目的地仍然是BottomSheetFragment(B)

当我在导航到 FragmentC 之前添加延迟时,应用程序不会崩溃。

lifecycleScope.launch {
                    delay(250)
                    findNavController().navigate(R.id.openCustomerLogin)
                }

我不喜欢delay 的解决方案,因为它不实用,而且在新的实现中很容易被遗忘。

抱歉,这篇文章很长,如果您能分享您对此的想法并为我提供帮助,我将不胜感激。

【问题讨论】:

    标签: android android-jetpack-navigation android-bottomsheetdialog


    【解决方案1】:

    我已经实现如下

    点击按钮时假设底部表格的代码如下

     private fun closeBottomSheet() {
            findNavController().previousBackStackEntry?.savedStateHandle?.set("refresh", true)
            findNavController().navigateUp()
        }
    

    片段A的以下代码

    val observer = LifecycleEventObserver { _, event ->
                if (event == Lifecycle.Event.ON_RESUME
                    && navBackStackEntry.savedStateHandle.contains("refresh")
                ) {
                    val result = navBackStackEntry.savedStateHandle.get<Boolean>("refresh")
                    if (result!!) {
                        result.run {
                            // whatever you do , go from fragment A to Fragment C
                            navBackStackEntry.savedStateHandle.remove<Boolean>("refresh")
                        }
                    }
                }
            }
        
    

    并检查您是否在 navigation.xml 中的片段 A 中定义了操作

    【讨论】:

    • 嗨 gaurav gupta,我尝试使用 findNavController().navigateUp() 而不是解雇。它仍然会立即崩溃(250)。片段 A 具有导航到片段 C 的定义,但片段 B 没有。
    • 如果结果为空,你的应用程序会在这种情况下崩溃,我不会使用这样的代码。你应该改为result?.run { ... }
    • 在 null 或 not null 的情况下,你编写这样的代码 result?.let { result -> // 不管你做什么 }
    猜你喜欢
    • 1970-01-01
    • 2021-04-18
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 2021-01-09
    • 1970-01-01
    • 1970-01-01
    • 2020-12-27
    相关资源
    最近更新 更多