In the Activity that will be displaying your NavHostFragment, inflate the graph like so:
val navHostFragment = navFragment as NavHostFragment
val inflater = navHostFragment.navController.navInflater
val graph = inflater.inflate(R.navigation.nav_whatever)
Where navFragment is the id you gave your fragment in XML, as above.
Step 3 [Crucial!]
Create a bundle to hold the arguments you want to pass to your startDestination fragment and add it to the graph's default arguments:
val bundle = Bundle()
// ...add keys and values
graph.addDefaultArguments(bundle)
OK, I found a solution to that problem thanks to Ian Lake from the Google team.
Let say you have an activity A that will start activity B with some intent data and you want to get that data in the startDestination you have two options here if you using safe args which is my case you could do
to read the args from the Intent. If you don't use safe args you can extract the data from the bundle your self-using requireActivity().intent?.extras which will return a Bundle you can use instead of the fragment getArguments() method. That's it I try it and everything works fine.
So for the people Still struggling with this. I found another way to do this without using Safe-Args and a step using @Elliot's Answer.
So lets say you received some arguments in Activity B from Activity A and Your Activity B has a fragment startDestination you are initialising the Nav controller like this:
from the Nav Controller you will have access to your graph which you have set in the XML like this and you can set the arguments in the defaultArguments:
I think this has changed again with the 1.0.0 release. And Google has hidden this information very well in the official documentation. Or at least I struggled to find it, but stumbled upon it in the Migrate to the Navigation component guide. How to pass arguments to the start destination is mentioned here: Pass activity destination args to a start destination fragment
In short
You have to set the navigation graph programatically:
Don't set the graph in the NavHostFragment XML declaration.
Read the extras from the receiver side:
val args by navArgs<ProductDetailsArgs>()
val productId = args.productId
Update: Google has said that the official documentation for passing arguments to the initial navigation target is indeed missing. Hopefully this is added soon as part of the Navigation component documentation.
So finally, I have found a solution to this issue.
At the time of writing this answer, I am using Navigation 2.2.0-alpha01
If you want to pass some data to the start destination directly as arguments from host activity, you need to manually set your host’s navigation graph inside the host activity’s onCreate() method, as shown below:
Get you navController:
val navController by lazy { findNavController(R.id.<your_nav_host_id>) }
Then in the host activity's onCreate()
val bundle = Bundle()
bundle.putString("some_argument", "some_value")
navController.setGraph(R.navigation.<you_nav_graph_xml>, bundle)
Or if you want to pass the whole intent extras as it is to the startDestination:
When you are setting the navGraph using setGraph() method, you should avoid setting the app:NavGraph attribute in
the NavHostFragment definition, because doing so results in inflating
and setting the navigation graph twice.
While reading these arguments in your startDestination fragment:
If you are using the Safe Args Plugin (which is very much recommended), then in your fragment:
private val args by navArgs<DummyFragmentArgs>()
Safe Args plugin would generate an Args class by appending Args to your fragment name. For example, if you fragment is called DummyFragment then Safe Args would generate a class called DummyFragmentArgs
where navArgs<> is an extension function defined in Android KTX
If you are not using Android KTX, you can get the args object like:
val args = DummyFragmentArgs.fromBundle(arguments!!)
Once you've acquired the arguments object, you can simply fetch your arguments:
args.someArgument
Notice how we passed "some_argument" as argument, and we are reading it as someArgument using Safe Args
If you are not using Safe Args (there is no reason to not use it though), you can access your arguments like this:
addDefaultArguments is no more in the latest versions of library. I have fixed the problem like this:
val navHostFragment = fragment_navigation_onboarding as NavHostFragment
val navController = navHostFragment.navController
val navInflater = navController.navInflater
val graph:NavGraph = navInflater.inflate(R.navigation.navigation_your_xml)
val model = Model()//you might get it from another activity
graph.addArgument("Data", NavArgument.Builder().setDefaultValue(model).build()) // This is where you pass the bundle data from Activity to StartDestination
navHostFragment.navController.graph = graph
After reading the solution i made one that suits for my needs,
this solution assume that the data sent to the activity that host this graph
on the start destination:
@Override
public void onAttach(Context context) {
super.onAttach(context);
// work around get get starting destination with activity bundle
userId = getActivity().getIntent().getIntExtra(KEY_USER_ID, -1);
}
You can pass data to your app's start destination. First, you must explicitly construct a Bundle that holds the data. Next, use one of the following methods to pass the Bundle to the start destination
you can set manually graph from the code and add argument with it and remove app:navGraph from xml and use this line of code in activity