66 votes

Composant de l'architecture de navigation - Passage de données d'argument à la destination de départ (startDestination)

J'ai une activité A qui lance l'activité B en lui transmettant des données d'intention. L'activité B héberge un graphe de navigation provenant du nouveau composant d'architecture de navigation. Je veux transmettre ces données d'intention au fragment startDestination comme argument. Comment faire ?

35voto

Elliot Schrock Points 591

En résumé, vous devez gonfler manuellement le graphe, ajouter les clés/valeurs aux defaultArgs et définir le graphe sur l'interface utilisateur. navController .

Étape 1

La documentation vous indique de définir le graphique dans le fichier <fragment> dans votre Activity de l'entreprise. Quelque chose comme ça :

<fragment
    android:id="@+id/navFragment"
    android:name="androidx.navigation.fragment.NavHostFragment"
    app:graph="@navigation/nav_whatever"
    app:defaultNavHost="true"
    />

ENLEVER la ligne qui fixe le graph= .

Étape 2

Dans l'activité qui affichera votre NavHostFragment gonfle le graphique comme suit :

val navHostFragment = navFragment as NavHostFragment
val inflater = navHostFragment.navController.navInflater
val graph = inflater.inflate(R.navigation.nav_whatever)

navFragment est l'identifiant que vous avez donné à votre fragment en XML, comme ci-dessus.

Étape 3 [Crucial !]

Créez un paquet pour contenir les arguments que vous voulez passer à l'utilisateur. startDestination et l'ajouter aux arguments par défaut du graphe :

val bundle = Bundle()
// ...add keys and values
graph.addDefaultArguments(bundle)

Étape 4

Définir le graphique sur l'hôte navController :

navHostFragment.navController.graph = graph

27voto

Ahmed Abd-Elmeged Points 724

OK, j'ai trouvé une solution à ce problème grâce à Ian Lake de l'équipe Google. Disons que vous avez une activité A qui va démarrer l'activité B avec certaines données d'intention et vous voulez obtenir ces données dans le startDestination, vous avez deux options ici si vous utilisez des args sûrs, ce qui est mon cas, vous pouvez faire ce qui suit

StartFragmentArgs.fromBundle(requireActivity().intent?.extras)

pour lire les args de l'Intent. Si vous n'utilisez pas d'args sécurisés, vous pouvez extraire les données du paquet vous-même en utilisant la fonction requireActivity().intent?.extras qui retournera un Bundle que vous pourrez utiliser à la place du fragment getArguments() méthode. Voilà, je l'essaie et tout fonctionne bien.

24voto

HvSimon Points 65

Il avait été fixé dans 1.0.0-alpha07 . Voir le détail.

La solution est similaire à la réponse d'Elliot Schrock, mais enveloppée par l'API officielle.

Nous devons gonfler manuellement NavHostFragment ou graph

Utilisez

NavHostFragment.create(R.navigation.graph, args)

Ou

navController.setGraph(R.navigation.graph, args)

Le site Arguments sont les données que nous voulons passer à la destination de départ.

19voto

Johan Paul Points 424

Je pense que cela a encore changé avec la version 1.0.0. Et Google a très bien caché cette information dans la documentation officielle. Ou du moins, j'ai eu du mal à la trouver, mais je suis tombé dessus dans la section Migrer vers le composant de navigation guide. La façon de passer des arguments à la destination de départ est mentionnée ici :

https://developer.Android.com/guide/navigation/navigation-migrate#pass_activity_destination_args_to_a_start_destination_fragment

En bref

  1. Vous devez définir le graphique de navigation de manière programmatique :
findNavController(R.id.main_content)
                .setGraph(R.navigation.product_detail_graph, intent.extras)
  1. Ne définissez pas le graphique dans la déclaration XML de NavHostFragment.
  2. Lisez les suppléments du côté du récepteur :
val args by navArgs<ProductDetailsArgs>()  
val productId = args.productId

Mise à jour : Google a indiqué que la documentation officielle concernant le passage d'arguments à la cible de navigation initiale est effectivement manquante. Nous espérons que cela sera bientôt ajouté dans la documentation du composant de navigation.

8voto

Praveen Singh Points 1261

J'ai finalement trouvé une solution à ce problème.

Au moment d'écrire cette réponse, j'utilise Navigation 2.2.0-alpha01

Si vous souhaitez transmettre certaines données à la destination de départ directement en tant qu'arguments de l'activité hôte, vous devez définir manuellement le graphique de navigation de votre hôte dans la méthode onCreate() de l'activité hôte, comme indiqué ci-dessous :

Prends ton navController :

val navController by lazy { findNavController(R.id.<your_nav_host_id>) }

Ensuite, dans l'activité de l'hôte onCreate()

val bundle = Bundle()
bundle.putString("some_argument", "some_value")
navController.setGraph(R.navigation.<you_nav_graph_xml>, bundle)

Ou si vous voulez transmettre l'ensemble des extras de l'intention tels quels à la startDestination :

navController.setGraph(R.navigation.<you_nav_graph_xml>, intent.extras)

Depuis intent.extras retournerait un Bundle uniquement

Lorsque vous définissez le navGraph à l'aide de la méthode setGraph(), vous devez éviter de définir l'attribut app:NavGraph dans la définition du segment NavHostFragment. dans la définition de NavHostFragment, car cela entraîne le gonflement et la et de définir deux fois le graphique de navigation.

En lisant ces arguments dans votre fragment startDestination :

Si vous utilisez le Plugin Safe Args (ce qui est très recommandé), puis dans votre fragment :

private val args by navArgs<DummyFragmentArgs>()

Le plugin Safe Args génère une classe Args en ajoutant Args au nom de votre fragment. Par exemple, si votre fragment s'appelle DummyFragment alors Safe Args génère une classe appelée DummyFragmentArgs

navArgs<> est une fonction d'extension définie dans Android KTX

Si vous n'utilisez pas Android KTX, vous pouvez obtenir l'objet args comme suit :

val args = DummyFragmentArgs.fromBundle(arguments!!)

Une fois que vous avez acquis l'objet arguments, vous pouvez simplement aller chercher vos arguments :

args.someArgument

Remarquez comment nous avons passé "some_argument" comme argument, et nous le lisons comme someArgument Utilisation de Safe Args

Si vous n'utilisez pas Safe Args (il n'y a aucune raison de ne pas l'utiliser cependant), vous pouvez accéder à vos arguments comme ceci :

arguments?.getString("some_argument")

Tout ceci est documenté dans la documentation sur la migration vers le composant de navigation ici : https://developer.Android.com/guide/navigation/navigation-migrate#pass_activity_destination_args_to_a_start_destination_fragment

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X