Verstehen Sie das Verhalten von startActivityForResult für Fragment und Aktivität

Dem gesamten startActivityForResult und onActivityResult ist eine 2-Wege-Kommunikation zwischen der Quell- und der Zielaktivität gestattet. Sein Fluss ist wie im Diagramm unten gezeigt.

Aus dem folgenden Fluss können wir den Fluss von onActivityResult von der Quell- zur Zielaktivität leicht verstehen

Der Quellenaktivitätsaufruf startActivityForResult durch Senden der Absicht zusammen mit dem Anforderungscode an Android SDK.

Android SDK öffnet dann die Aktivität entsprechend, wie in der Absicht angegeben.
Sobald die Zielaktivität ihren Job beendet hat, kehrt sie zu ihrer Aufruferaktivität zurück.

Das Ergebnis kann mit setResult zurückgesendet werden, indem der resultCode und die Absicht gesendet werden

Hier einige Hinweise:

Der resultCode wird von der Zielaktivität verwendet, um ihrer Quellaktivität den Status mitzuteilen (z. B. OK, Abbrechen usw.).

Der Anforderungscode wird von der Quellaktivität verwendet, um zu erfahren, welche Zielaktivität den Anruf zurückgibt.

Wir konnten sehen, dass die Zielaktivität keine Sichtbarkeit des Anforderungscodes hat.

Undokumentierter startActivityForResult-Fragmentfluss

In Fragment müssen wir auch die Funktion startActivityForResult aufrufen und die Funktion onActivityResult überschreiben.

Dies wirft mehrere Fragen auf … zB Wie funktioniert es? Ist es das gleiche wie die Aktivität startActivityForResult und onActivityResult? Wie sind sie verwandt?
Die kurze Antwort ist, sie sind ähnlich, aber subtil anders. Eine häufige Ursache für Verwirrung und Fehler. Daher ist es wichtig, die Ähnlichkeiten und Unterschiede zu verstehen.

Der dargestellte Fragmentfluss.

Unten ist das Diagramm, das deutlich zeigt, wie alles zusammenarbeitet. Die Unterschiede zum Fluss startActivityForResult und onActivityResult der Aktivität sind ROT dargestellt.

Lassen Sie uns näher darauf eingehen.

Wenn wir Fragments startActivityForResult aufrufen (Hinweis: KEINE Aktivität?.startActivityForResult), ist die Erstellung der Zielaktivität gleich. Der Unterschied ist jedoch das onActivityResult .

startActivityForResult() muss es von der fragment behandeln onActivityForResult()

getActivity().startActivityForResult() muss es von activity onActivityForResult()

Wenn Sie sich auf einem fragment befinden und das Ergebnis auf fragment verarbeiten möchten, verwenden Sie onActivityForResult(), andernfalls, wenn Sie es von activity des Fragments verarbeiten möchten, verwenden Sie getActivity.startActivityForResult()

Wenn Android SDK onActivityResult zurückgibt, wurde der Anforderungscode geändert. Ein 0xP0000 wird an den ursprünglichen requestCode angehängt.

Der P-Wert beginnt bei 1 und wird für jedes onActivityResult erhöht, das vom selben Zielfragment aufgerufen wird. (Wenn ein anderes Zielfragment aufgerufen wird, wird der P-Wert zurückgesetzt).

zB wenn der ursprüngliche Anforderungscode 0xFF (dh 255) ist, ist der Anforderungscode beim ersten Mal 0x100FF . Das zweite Mal Rückkehr requestCode wird 0x200FF sein.

Bei der Rückkehr zum onActivityResult der Quellaktivität wird erwartet, dass es super aufrufen sollte.onActivityResult, das sich in FragmentActivity (dem übergeordneten Element von AppCompatActivity) befindet

Das onActivityResult in FragmentActivity extrahiert dann den P-Wert (unter Verwendung von requestCode >> 16). Das P ist der Index des Arrays, in dem das Quellfragment gespeichert ist. (zB wenn requestCode 0x200FF ist, dann 0x200FF >> 16 = 2)

Mit dem P-Wert hat es nun Zugriff auf das Quellfragment, das in Schritt 9 unten verwendet wird.

Jetzt wird der P-Wert aus dem Anforderungscode entfernt (mit requestCode & 0xffff ), um zum ursprünglichen Anforderungscode zurückzukehren (z. wenn requestCode 0x200FF ist, dann 0x200FF & 0xffff = 0xFF)

Da jetzt der ursprüngliche Anforderungscode abgerufen wird, den das Quellfragment erstellt hat, kann das onActivityResult des Quellfragments mit dem ursprünglichen onActivityResult aufgerufen werden Anforderungscode.

Einige grundlegende Punkte, die wissen wollen.

A. Das Verhalten von Activity’s startActivityForResult unterscheidet sich von Fragment’s startActivityForResult

Wenn wir in Fragment activity?.startActivityForResult(...) aufrufen, wird Fragment’s onActivityResult nicht automatisch aufgerufen.

B. Wenn wir das onActivityResult der Aktivität überschreiben, stellen Sie sicher, dass wir super haben.onActivityResult anstelle von

Wenn wir die onActivityResult der Quellaktivität überschreiben, aber vergessen, super.onActivityResult zu haben, wird die onActivityResult des Fragments nicht aufgerufen.

C. Der in onActivityResult der Aktivität onActivityResult unterscheidet sich von dem in

angegebenen Fragment Aus dem Grund, dass Android SDK P an requestCode angehängt hat. in der Aktivität onActivityResult erhalten wir dort niemals das identische requestCode . Dies führt manchmal zu Verwirrung beim Entwickler, wenn der Code dort debuggt wird.

D. Wenn eine Aktivität aus dem Status wiederhergestellt wird (dh onStateInstance != null), sollte es vermeiden, sein Fragment neu zu erstellen.

Wenn onActivityResult aufgerufen wird, wurde versucht, das ursprüngliche Fragment abzurufen. Dies wird auch für die Aktivität durchgeführt, die aus einem getöteten Zustand wiederhergestellt wird (z. B. emuliert mit Aktivität nicht beibehalten).

Wenn der Entwickler das Fragment also jedes Mal neu erstellt, wenn onCreate aufgerufen wird (unabhängig davon, ob es sich um einen wiederhergestellten Zustand handelt oder nicht), wird das ursprüngliche Fragment, das wiederhergestellt wurde, zerstört, und onActivityResult des Aufrufers wird das Fragment auf mysteriöse Weise nicht aufgerufen.

Dies ist eine Falle, auch für viele erfahrene Entwickler und App auf dem Gebiet veröffentlicht, da es sehr schwer zu einem identifizierten Fehler ist (da es nicht jedes Mal passiert, und erfordern einen komplexeren Fluss auszulösen).

Danke fürs Lesen…