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 ?
Réponses
Trop de publicités?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)
Où 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
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.
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.
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 :
En bref
- 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)
- Ne définissez pas le graphique dans la déclaration XML de NavHostFragment.
- 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.
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
où 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