Android Navigation Architecture Component: How to

2019-07-07 09:32发布

问题:

I have an activity which has a NavHostFragment. The activity receives certain values in its intent. I want to pass this data to the first fragment i.e startDestination of the navigation graph. I couldn't find any documentation regarding this.

I have already gone through this question on SO but I can't seem to find the addDefaultArguments method for navController.getGraph().

Is it possible to pass bundle to startDestination?

回答1:

i also came across same issue,

This is how i resolved it:

  1. Remove the the xml setup of NavHostFragment from your_activity.xml : i.e remove app:navGraph="@navigation/nav_graph

This is how your XML Should look like.

        <fragment
        android:id="@+id/nav_host"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        />
  1. Add Setup for NavHostFragment Programatically in onCreate() of activity. And pass bundle data using NavGraph.addDefaultArguments(bundleData) api

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.editor_layout)
            setupNavigation()
        }
    
        private fun setupNavigation() {
            val navHostFragment = nav_host as NavHostFragment
            val navController = navHostFragment.navController
            val navInflater = navController.navInflater
            val graph = navInflater.inflate(R.navigation.nav_graph)
            graph.addDefaultArguments(intent!!.extras!!) // This is where you pass the bundle data from Activity to StartDestination 
            navHostFragment.navController.graph = graph
        }
    

UPDATE:

Dependencies in my Project Gradle file:

dependencies {

    def nav_version = "1.0.0-alpha08"

    implementation "android.arch.navigation:navigation-fragment:$nav_version" // use -ktx for Kotlin
    implementation "android.arch.navigation:navigation-ui:$nav_version" // use -ktx for Kotlin}
}

NOTE: In Navigation Component version 1.0.0-alpha09 for some reason google have no method as addDefaultArguments() might be fixed soon. But lower version's have addDefaultArguments() method.I have checked both in java and kotlin so try using 1.0.0-alpha07 or 1.0.0-alpha08



回答2:

you can add arguments in your graph like this

<fragment
  android:id="@+id/exampleFragment"
  android:label="example_fragment"
  android:name="com.example.yourapp.ui.ExampleFragment"
  tools:layout="@layout/example_fragment">
<argument
  android:name="exampleArgs"
  app:argType="reference"
  android:defaultValue="@string/example"/>
</fragment>

https://developer.android.com/guide/navigation/navigation-pass-data



回答3:

I cannot find this method, too. It is not existant in the architecture components documentation.

But the is another way to set arguments to the start destination:

// Kotlin Code, in Fragment
with(findNavController().graph) {
    get(startDestination).addArgument(...)
}


回答4:

I checked the source code an saw that there a lot of changes regarding navigation destination and arguments. I think the proper way to pass arguments to start destination is using 'addArgument' method, something like this:

val argument1 = 1 //First value
val argument2 = "Value" //Second value
val navArgument1=NavArgument.Builder().setDefaultValue(argument1).build()
val navArgument2=NavArgument.Builder().setDefaultValue(argument2).build()
navController.getGraph().addArgument("Key1",navArgument1)
navController.getGraph().addArgument("Key2",navArgument2)

Maybe there is a better way, but i didn't found one.



回答5:

class MainActivity : BaseActivity()  {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val navHostFragment = container as NavHostFragment
        val inflater = navHostFragment.navController.navInflater
        val graph = inflater.inflate(R.navigation.main_nav)

        var data : Data  = intent.getParcelableExtra("DATA") as Data
        var bundle : Bundle = Bundle()
        bundle.putParcelable("DATA", data)
        graph.addDefaultArguments(bundle)
        graph.addDefaultArguments(intent!!.extras!!)
        navHostFragment.navController.graph = graph

    }
}

Add the above code in Activity for sending the data using using navigation

override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        var data = NavHostFragment.findNavController(this).graph.defaultArguments.getParcelable("DATA") as Booking

}

Add the above code in fragment side