Android jetpack navigation component result from dialog

后端 未结 3 599
自闭症患者
自闭症患者 2021-02-08 12:44

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 fr

相关标签:
3条回答
  • 2021-02-08 13:05

    Thanks to @NataTse and also the official docs, i came up with the extensions so that hopefully less boilerplate code to write:

    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)
            }
        })
    }
    
    0 讨论(0)
  • 2021-02-08 13:15

    In Navigation 2.3.0-alpha02 and higher, NavBackStackEntry gives access to a SavedStateHandle. A SavedStateHandle is a key-value map that can be used to store and retrieve data. 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. 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. To do so, retrieve the NavBackStackEntry by using the getCurrentBackStackEntry() API and then observe the LiveData provided by SavedStateHandle.

    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.

    navController.previousBackStackEntry?.savedStateHandle?.set("key", result)
    
    0 讨论(0)
  • 2021-02-08 13:15

    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
            )
    
    0 讨论(0)
提交回复
热议问题