Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Equivalent of startActivityForResult() with Android Architecture Navigation

I have a workflow with 3 screens. From "screen 1" to access to "screen 2", the user must accept some kind of terms and conditions that I call in my picture "modal". But he only has to accept those conditions once. The next time he is on the first screen, he can go directly to screen 2. The user can chose to NOT accept the terms, and therefore we go back to "screen 1" and do not try to go to "screen 2".

App workflow

I am wondering how to do it with the new navigation component.

Previously, what I would do it:

  • On screen 1, check if the user must accept the conditions
  • If no, start "screen 2" activity
  • If yes, use startActivityForResult() and wait result from the modal. Mark the terms as accepted. Start "screen 2"

But with the navigation graph, there is no way to start a Fragment to obtain a result.

I could mark the terms as accepted in the "modal" screen and start the "screen 2" from there. The thing is that to access to the screen 2, I need to do a network request. I do not want to duplicate the call to the API and processing its outcome in both "screen 1" and "modal".

Is there a way to go back from "modal" to "screen 1" with some information (user accepted the terms), using Jetpack navigation?

Edit: I currently get around it by using the same flow that Yahya suggests below: using an Activity just for the modal and using startActivityForResult from the "screen 1". I am just wondering if I could continue to use the navigation graph for the whole flow.

like image 583
Jonas Schmid Avatar asked Jun 05 '18 14:06

Jonas Schmid


People also ask

What is the replacement of startActivityForResult?

Among the contracts available, the StartActivityForResult contract is the replacement to the startActivityForResult . The callback is to be called once the activity result is available.

What is startActivityForResult in Android?

By the help of android startActivityForResult() method, we can send information from one activity to another and vice-versa. The android startActivityForResult method, requires a result from the second activity (activity to be invoked).

What is NavController in Android?

NavController manages app navigation within a NavHost . Apps will generally obtain a controller directly from a host, or by using one of the utility methods on the Navigation class rather than create a controller directly. Navigation flows and destinations are determined by the navigation graph owned by the controller.

What is jetpack navigation?

Android Jetpack's Navigation component helps you implement navigation, from simple button clicks to more complex patterns, such as app bars and the navigation drawer. The Navigation component also ensures a consistent and predictable user experience by adhering to an established set of principles.


1 Answers

In the 1.3.0-alpha04 version of AndroidX Fragment library they introduced new APIs that allow passing data between Fragments.

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 existing Activity#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)

like image 180
Ziem Avatar answered Sep 20 '22 20:09

Ziem