Equivalent of startActivityForResult() with Android Architecture Navigation
There are a couple of alternatives to the shared view model.
fun navigateBackWithResult(result: Bundle) as explained here https://medium.com/google-developer-experts/using-navigation-architecture-component-in-a-large-banking-app-ac84936a42c2
Create a callback.
ResultCallback.kt
interface ResultCallback : Serializable {
fun setResult(result: Result)
}
Pass this callback as an argument (note it has to implement Serializable and the interface needs to be declared in its own file.)
<argument android:name="callback"
app:argType="com.yourpackage.to.ResultCallback"/>
Make framgent A implement ResultCallback, fragment B by will get the arguments and pass the data back through them, args.callback.setResult(x)
It looks like there isn't equivalent for startActivityForResult
in Navigation Component right now. But if you're using LiveData and ViewModel you may be interested in this article. Author is using activity scoped ViewModel and LiveData to achieve this for fragments.
In the 1.3.0-alpha04 version of AndroidX Fragment library they introduced new APIs that allow passing data between Fragment
s.
Added support for passing results between two Fragments via new APIs on FragmentManager. This works for hierarchy fragments (parent/child), DialogFragments, and fragments in Navigation and ensures that results are only sent to your Fragment while it is at least STARTED. (b/149787344)
FragmentManager
gained two new methods:
FragmentManager#setFragmentResult(String, Bundle)
which you can treat similiarly to the existingActivity#setResult
;FragmentManager#setFragmentResultListener(String, LifecycleOwner, FragmentResultListener)
which allows you to listen/observe result changes.
How to use it?
In FragmentA
add FragmentResultListener
to the FragmentManager
in the onCreate
method:
setFragmentResultListener("request_key") { requestKey: String, bundle: Bundle ->
val result = bundle.getString("your_data_key")
// do something with the result
}
In FragmentB
add this code to return the result:
val result = Bundle().apply {
putString("your_data_key", "Hello!")
}
setFragmentResult("request_key", result)
Start FragmentB
e.g.: by using:
findNavController().navigate(NavGraphDirections.yourActionToFragmentB())
To close/finish FragmentB
call:
findNavController().navigateUp()
Now, your FragmentResultListener
should be notified and you should receive your result.
(I'm using fragment-ktx
to simplify the code above)