对话框中的Android Jetpack导航组件结果

时间:2019-06-17 04:52:13

标签: android android-architecture-navigation jetpack

到目前为止,我仅使用导航组件就可以成功导航到对话框并返回。问题是,我必须在对话框中做一些事情,然后将结果返回到调用对话框的片段中。

一种方法是使用共享的viewmodel。但是为此,我必须使用.of(activity),即使我不再需要它,也使我的应用仅占用内存。

另一种方法是重写show(fragmentManager,id)方法,获取对片段管理器的访问,并从中访问先前的片段,然后可以将其设置为targetfragment。在实现回调接口之前,我已经使用了targetFragment方法,因此我的对话框可以将结果通知给TargetFragment。但是在导航组件方法中,它感觉很笨拙,并且可能在某一点或另一点停止工作。

还有其他方法可以做我想要的吗?也许有一种方法可以解决第一种方法的问题?

3 个答案:

答案 0 :(得分:7)

在Navigation 2.3.0-alpha02及更高版本中,NavBackStackEntry允许访问SavedStateHandle。 SavedStateHandle是一个键值映射,可用于存储和检索数据。这些值会在进程终止(包括配置更改)时保持不变,并通过同一对象保持可用。通过使用给定的SavedStateHandle,您可以在目标之间访问和传递数据。这是一种有用的机制,它是一种将数据从堆栈中弹出后从目的地取回数据的机制。

要将数据从目标B传递回目标A,首先将目标A设置为在其SavedStateHandle上侦听结果。为此,请使用getCurrentBackStackEntry()API检索NavBackStackEntry,然后观察SavedStateHandle提供的LiveData。

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val navController = findNavController();
// We use a String here, but any type that can be put in a Bundle is supported
navController.currentBackStackEntry?.savedStateHandle?.getLiveData("key")?.observe(
    viewLifecycleOwner) { result ->
    // Do something with the result.
}

}

在目标B中,必须使用getPreviousBackStackEntry()API在目标A的SavedStateHandle上设置结果。

navController.previousBackStackEntry?.savedStateHandle?.set("key", result)

答案 1 :(得分:4)

感谢@NataTse和official docs,我想出了扩展名,希望可以写出更少的样板代码:

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

fun <T>Fragment.getNavigationResult(@IdRes id: Int, key: String, onResult: (result: T) -> Unit) {
    val navBackStackEntry = findNavController().getBackStackEntry(id)

    val observer = LifecycleEventObserver { _, event ->
        if (event == Lifecycle.Event.ON_RESUME
            && navBackStackEntry.savedStateHandle.contains(key)
        ) {
            val result = navBackStackEntry.savedStateHandle.get<T>(key)
            result?.let(onResult)
            navBackStackEntry.savedStateHandle.remove<T>(key)
        }
    }
    navBackStackEntry.lifecycle.addObserver(observer)

    viewLifecycleOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
        if (event == Lifecycle.Event.ON_DESTROY) {
            navBackStackEntry.lifecycle.removeObserver(observer)
        }
    })
}

答案 2 :(得分:2)

当您将“导航组件”与对话框一起使用时,这部分代码看起来不太好(对我而言,它什么也没返回)

navController.currentBackStackEntry?.savedStateHandle?.getLiveData("key")?.observe(
viewLifecycleOwner) { result ->
// Do something with the result.}

您需要尝试从official docs出发,这对我有很大帮助

这部分对我有用:

 val navBackStackEntry = navController.getBackStackEntry(R.id.target_fragment_id)

    // Create observer and add it to the NavBackStackEntry's lifecycle
    val observer = LifecycleEventObserver { _, event ->
        if (event == Lifecycle.Event.ON_RESUME
            && navBackStackEntry.savedStateHandle.contains("key")
        ) {
            val result =
                navBackStackEntry.savedStateHandle.get<Boolean>("key")
            // Do something with the result

        }
    }
    navBackStackEntry.lifecycle.addObserver(observer)

    // As addObserver() does not automatically remove the observer, we
    // call removeObserver() manually when the view lifecycle is destroyed
    viewLifecycleOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
        if (event == Lifecycle.Event.ON_DESTROY) {
            navBackStackEntry.lifecycle.removeObserver(observer)
        }
    })

在对话框中:

navController.previousBackStackEntry?.savedStateHandle?.set(
            "key",
            true
        )