I am using navigation component's type safe APIs to navigate. The app which I inherited uses several activities (2-3), and fragments everywhere else. One of the flows requires to navigate from a fragment of one activity to another activity. This works ok when I declare my graph destinations like so:
//Routes.kt
@Serializable
data class SecondScreen(val foo: Foo, val bar: String = "")
//FirstActivity.kt
findNavController().createGraph(SomeStartDestination) {
activity<SecondScreen>(
typeMap = mapOf(
typeOf<Foo> to NavType.EnumType(Foo::class.java)
)
) {
activityClass = SecondActivity::class
}
}
//SecondActivity.kt
fun onCreate() {
val route = findNavController().currentBackStackEntry?.toRoute<SecondScreen>()
print(route?.foo) // null
print(route?.bar) // null
}
The part that does not work is retrieving the args that were passed along. I suspect that when the SecondActivity gets created, its NavHost and NavController start out with an empty backstack. If I grab the intent extras, it seems to extract the data ok, yet I feel that it's more of a workaround than an idiomatic solution. I looked around but did not come across any documentation for such a scenario. Am I missing something?
If you want findNavController.currentBackStackEntry?.toRoute<T>() to work in the activity,call navcontroller.setGraph(..., inten.extra) early in onCreate .
If you only need the arg in activity, read intent.extra directly (clean & simple).
Here is example to set Nav graph with inten.extras So toRoute<T>() works.
When the activity starts, pass the incoming Intent.extras to NavController via setGraph(graphResId,startDestinationArg) (or setGraph(NavGraph,bundel)).
// Get NavController from NavHostFragment
val navHost = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
val navController = navHost.navController
// Option A: if graph is defined as resource, pass intent.extras when setting graph
navController.setGraph(R.navigation.your_graph, intent.extras)
// Option B: if you already have a NavGraph instance, do:
// navController.setGraph(navController.graph, intent.extras)
// Now the NavController has the startDestination entry populated with arguments
val route = navController.currentBackStackEntry?.toRoute<SecondScreen>()
Log.d("Args", "route foo=${route?.foo} bar=${route?.bar}")
Second Activity class , Put below code in onCreate Method
// If your route is serializable/Parcelable or you know how args were packed,
// this is the direct way:
val extras = intent.extras
extras?.let {
// If you used a single-bundle-arg convention, convert it:
val route: SecondScreen? = extras.toRoute() // if you have helper
// or extract each arg:
val bar = extras.getString("barArgName")
val foo = extras.getSerializable("fooArgName") as? Foo
}
Try above solution
Thank you