Start Fragment For Result With Navigation Component

Learn How To Start A Fragment For Result Without Hassle Using Navigation Component.

Web & Mobile Development


Introduction

A lot has changed over the last couple of years when it comes to our development approach in Android. We have a simpler dependency framework in the form of Dagger-Hilt, AndroidX libraries which have improved the use of many android components, co-routines which have saved us from callback hell, a much improved ORM library in Room and yes, a much, much better navigation system. Without wasting too much of your time, let's get into how we can start another fragment for results.

Let's Dive In

Suppose you want to move from Fragment A to Fragment B and you'd like to get some results back from Fragment B when returning to Fragment A, you'll set up Fragment A like this:
class FragmentA : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        //Observe the result to be set by Fragment B in the stateHandle of the currentBackStackEntry
        val currentBackStackEntry = findNavController().currentBackStackEntry
        val savedStateHandle = currentBackStackEntry?.savedStateHandle
        savedStateHandle?.getLiveData<String>(RESULT_FROM_FRAGMENT_B)
            ?.observe(currentBackStackEntry, Observer { result ->
                print(result)
            })
    }

    private fun navigateToFragmentB() {
        val navDirection = FragmentADirection.actionFragmentAToFragmentB()
        findNavController().navigate(navDirection)
    }

    companion object {
        const val RESULT_FROM_FRAGMENT_B = "RESULT_FROM_FRAGMENT_B"
    }
}

Then you'll set up Fragment B to set the result that is being observed by Fragment A
class FragmentB : Fragment() {

    private fun navigateBackToFragmentA() {
        //Setting the result in the stateHandle of the previousBackStackEntry before navigating back to Fragment A
        //will allow Fragment A to access the result in the stateHandle of its currentBackStackEntry
        val savedStateHandle = findNavController().previousBackStackEntry?.savedStateHandle
        savedStateHandle?.set(FragmentA.RESULT_FROM_FRAGMENT_B, "result")
        findNavController().navigateUp()
    }
}

That's it! You can easily navigate to any fragment and get the result by setting the stateHandle of the previousBackStackEntry and observing the result in the stateHandle of the currentBackStackEntry.

Looking for a new challenge? Join Our Team

Like 5 likes
Anu Karounwi
Android engineer at oozou
Share:

Join the conversation

This will be shown public
All comments are moderated

Comments

Naser
December 24th, 2020
Thank you very much for sharing your innovative solutions.
My question is if we are observing a String in Fragment A, then why we pass a Boolean in fragment B?

Anu
December 24th, 2020
Thanks for catching the error @Naser. I've updated the post

Lynn
January 5th, 2021
with navigation_version as 2.3.0 and
// Navigation
implementation "android.arch.navigation:navigation-fragment-ktx:$version_navigation"
implementation "android.arch.navigation:navigation-ui-ktx:$version_navigation"

I cannot access currentBackStackEntry using: navController.currentBackStackEntry... Won't compile. Anything I am missing here?

Anu
January 5th, 2021
@Lynn try using the latest version of navigation component which is 2.3.2. It will also help if you can share the error you're getting so I can help you further.

Get our stories delivered

From us to your inbox weekly.