简体   繁体   English

Android jetpack 导航组件结果来自对话框

[英]Android jetpack navigation component result from dialog

So far I'm successfully able to navigate to dialogs and back using only navigation component.到目前为止,我只能使用导航组件成功导航到对话框并返回。 The problem is that, I have to do some stuff in dialog and return result to the fragment where dialog was called from.问题是,我必须在对话框中做一些事情并将结果返回到调用对话框的片段。

One way is to use shared viewmodel.一种方法是使用共享视图模型。 But for that I have to use .of(activity) which leaves my app with a singleton taking up memory, even when I no longer need it.但是为此,我必须使用 .of(activity) ,即使我不再需要它,它也会让我的应用程序单例占用内存。

Another way is to override show(fragmentManager, id) method, get access to fragment manager and from it, access to previous fragment, which could then be set as targetfragment.另一种方法是覆盖 show(fragmentManager, id) 方法,访问片段管理器并从中访问前一个片段,然后可以将其设置为目标片段。 I've used targetFragment approach before where I would implement a callback interface, so my dialog could notify targetFragment about result.我在实现回调接口之前使用过 targetFragment 方法,因此我的对话框可以将结果通知 targetFragment。 But in navigation component approach it feels hacky and might stop working at one point or another.但是在导航组件方法中,它感觉很笨拙,可能会在某一时刻停止工作。

Any other ways to do what I want?还有其他方法可以做我想做的事吗? Maybe there's a way to fix issue on first approach?也许有办法解决第一种方法的问题?

In Navigation 2.3.0-alpha02 and higher, NavBackStackEntry gives access to a SavedStateHandle.在 Navigation 2.3.0-alpha02 及更高版本中,NavBackStackEntry 允许访问 SavedStateHandle。 A SavedStateHandle is a key-value map that can be used to store and retrieve data. SavedStateHandle 是可用于存储和检索数据的键值映射。 These values persist through process death, including configuration changes, and remain available through the same object.这些值在进程死亡期间持续存在,包括配置更改,并通过同一对象保持可用。 By using the given SavedStateHandle, you can access and pass data between destinations.通过使用给定的 SavedStateHandle,您可以在目标之间访问和传递数据。 This is especially useful as a mechanism to get data back from a destination after it is popped off the stack.这作为一种在数据从堆栈中弹出后从目的地取回数据的机制特别有用。

To pass data back to Destination A from Destination B, first set up Destination A to listen for a result on its SavedStateHandle.要将数据从 Destination B 传回 Destination A,首先设置 Destination A 以侦听其 SavedStateHandle 上的结果。 To do so, retrieve the NavBackStackEntry by using the getCurrentBackStackEntry() API and then observe the LiveData provided by 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.
}

} }

In Destination B, you must set the result on the SavedStateHandle of Destination A by using the getPreviousBackStackEntry() API.在目标 B 中,您必须使用 getPreviousBackStackEntry() API 在目标 A 的 SavedStateHandle 上设置结果。

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

Thanks to @NataTse and also the official docs , i came up with the extensions so that hopefully less boilerplate code to write:感谢@NataTse 和官方文档,我想出了扩展,以便希望编写更少的样板代码:

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)
        }
    })
}

When you use Navigation Component with dialogs, this part of code looks not so good (for me it returned nothing)当你在对话框中使用导航组件时,这部分代码看起来不太好(对我来说它什么都不返回)

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

You need to try way from official docs and it help me a lot你需要从官方文档中尝试方法,它对我有很大帮助

This part is working for me:这部分对我有用:

 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)
        }
    })

And in your dialog:在你的对话中:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Android Jetpack 导航组件条件导航问题 - Android Jetpack Navigation component Condtional navigation issue 使用Android Jetpack导航组件与Android BottomAppBar - Using Android Jetpack Navigation component with Android BottomAppBar 使用jetpack导航组件从一个底页导航到另一个底页时如何弹出底页对话框 - How to pop the bottomsheet dialog when navigating from one bottomsheet to another using jetpack navigation component Android Jetpack Navigation组件与BottomAppBar菜单交互 - Android Jetpack Navigation component and BottomAppBar menu interaction Android 喷气背包组件 - 在导航抽屉点击烤面包 - Android jetpack component - toast on navigation drawer click Android 应用程序错误 android.view.InflateException。 使用 Jetpack 导航组件 - Android app error android.view.InflateException. With Jetpack Navigation Component Android Jetpack 导航组件问题,以启动片段为根目标 - Android Jetpack Navigation component issue with splash fragment as root destination Android Jetpack 导航组件太慢。 有什么问题? - Android Jetpack Navigation Component too slow. What's the problem? Android Jetpack导航组件出现问题,带有编辑文本掩码和错误消息 - Android Jetpack Navigation Component issue with edit text masks and error messages 为什么 Android Jetpack 底部导航组件如此滞后? - Why Android Jetpack Bottom Navigation Component is so laggy?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM