Comprendre le comportement de startActivityForResult pour le fragment et l’activité

L’ensemble de startActivityForResult et onActivityResult est autorisé à une communication bidirectionnelle entre l’activité source et l’activité de destination. Son débit est comme indiqué dans le diagramme ci-dessous.

À partir du flux ci-dessous, Nous pouvons facilement comprendre le flux de OnActivityResult de l’Activité Source à l’Activité de Destination

L’appel d’activité source, startActivityForResult en envoyant l’intention avec le code de demande au SDK Android.

Le SDK Android ouvre ensuite l’activité en conséquence, comme indiqué dans l’intention.
Une fois que l’activité de destination a terminé son travail, elle revient à son activité d’appelant.

Il peut renvoyer le résultat en utilisant setResult en envoyant le code de résultat et l’intention

Plusieurs notes ici:

Le code de résultat est utilisé par l’activité de destination pour signaler à son activité source son état (par exemple, OK, Annuler, etc.).

Le code de requête est utilisé par l’activité source pour savoir quelle activité de destination renvoie l’appel.

Nous avons pu voir que l’activité de destination n’a aucune visibilité du code de la demande.

Flux de fragments startActivityForResult non documenté

Dans Fragment, nous avons également la fonction startActivityForResult à appeler, ainsi que la fonction onActivityResult à remplacer.

Cela soulève plusieurs questions… par exemple, comment cela fonctionne-t-il? Est-ce la même chose que startActivityForResult et onActivityResult de l’activité ? Comment sont-ils liés?
La réponse courte est qu’ils sont similaires mais subtilement différents. Une cause fréquente de confusion et de bug. Il est donc important de comprendre la similitude et les différences.

Le flux de fragments illustré.

Voici le diagramme qui illustre clairement comment tout cela fonctionne ensemble. Les différences avec le flux startActivityForResult d’activity et onActivityResult sont colorées en ROUGE.

Développons-le plus.

Lorsque nous appelons startActivityForResult du fragment (remarque: PAS d’activité?.startActivityForResult), la création de l’activité de destination est la même. Cependant, la différence est l’onActivityResult.

startActivityForResult() doit le gérer à partir des fragment onActivityForResult()

getActivity().startActivityForResult() doit le gérer à partir du activity onActivityForResult()

Si vous êtes sur un fragment et que vous souhaitez gérer le résultat sur le fragment, utilisez onActivityForResult(), sinon, si vous voulez le gérer à partir du activity du fragment, utilisez getActivity.startActivityForResult()

Lorsque le SDK Android retourne onActivityResult, le code de demande a été modifié. Un 0xP0000 est ajouté au code de requête d’origine.

La valeur P commence à partir de 1, et incrémentée pour chaque onActivityResult est appelée à partir du même fragment de destination. (Si un autre fragment de destination est appelé, la valeur P est réinitialisée).

par exemple, si le code de demande d’origine est 0xFF (c’est-à-dire 255), le code de demande retourné la première fois sera 0x100FF. Le deuxième code de demande de retour sera 0x200FF.

Lors du retour à onActivityResult de l’activité source, il est prévu qu’elle appelle super.onActivityResult, qui réside dans FragmentActivity (le parent de AppCompatActivity)

onActivityResult dans FragmentActivity extraira ensuite la valeur P (en utilisant requestCode > > 16). Le P est l’index du tableau où le fragment source est stocké. (par exemple, si le code de demande est 0x200FF, alors 0x200FF >> 16 = 2)

En utilisant la valeur P, il a maintenant accès au fragment source, qui est utilisé à l’étape 9 ci-dessous.

Maintenant, il supprime la valeur P du code de requête (en utilisant le code de requête & 0xffff), pour revenir au code de requête d’origine (par exemple si le code de requête est 0x200FF, alors 0x200FF & 0xffff = 0xFF)

Comme maintenant il obtient le code de requête d’origine créé par le fragment source, il peut appeler onActivityResult du fragment source avec le code de requête d’origine.

Quelques points de base que vous voulez savoir.

A. Le comportement de startActivityForResult de l’activité est différent de startActivityForResult du fragment

Dans Fragment, si nous appelons activity?.startActivityForResult(...), Alors le Fragment onActivityResult ne sera pas appelé automatiquement.

B. Si nous remplaçons onActivityResult d’activity, assurez-vous d’avoir super.onActivityResult en place

Si nous remplaçons l’activité source onActivityResult, mais oublions d’avoir super.onActivityResult alors le fragment onActivityResult ne sera pas appelé.

C. Le code de requête vu dans onActivityResult de l’activité est différent du fragment fourni

En raison de la raison pour laquelle le SDK Android a ajouté P au requestCode, dans le onActivityResult de l’activité, nous n’y obtiendrons jamais le requestCode identique. Cela provoque parfois de la confusion pour le développeur lors du débogage du code.

D. Lorsqu’une activité est restaurée à partir de l’état (c’est-à-dire onStateInstance!= null), il faut éviter de recréer son fragment.

Lorsque onActivityResult est appelé, il a essayé de récupérer le fragment d’origine. Ceci est également effectué pour l’activité qui est restaurée à partir d’un état tué (par exemple, émulée à l’aide de Ne pas conserver l’activité).

Donc, si le développeur recrée le Fragment à chaque appel d’OnCreate (qu’il s’agisse d’un état restauré ou non), le Fragment d’origine restauré sera détruit et onActivityResult de l’appelant, le fragment ne sera mystérieusement pas appelé.

C’est un piège même pour de nombreux développeurs expérimentés et applications publiées sur le terrain, car il est très difficile d’identifier un bogue (car cela ne se produit pas à chaque fois, et nécessite un flux plus complexe pour se déclencher).

Merci d’avoir lu…