förstå beteendet hos startActivityForResult för Fragment och aktivitet

hela startActivityForResult och onActivityResult tillåts en 2-vägs kommunikation mellan källaktiviteten och destinationsaktiviteten. Dess flöde är som visas i diagrammet nedan.

från nedanstående flöde kan vi lätt förstå flödet av OnActivityResult från Källaktivitet till Destinationsaktivitet

källaktivitetssamtalet, startActivityForResult genom att skicka in avsikten tillsammans med förfrågningskoden till Android SDK.

Android SDK öppnar sedan aktiviteten i enlighet med vad som anges i avsikten.
när destinationsaktiviteten är klar med sitt jobb återgår den till sin uppringningsaktivitet.

det kan skicka resultatet tillbaka med setResult genom att skicka in resultatkoden och avsikten

flera anteckningar här:

resultatkoden används av destinationsaktiviteten för att flagga till sin källaktivitet vad det är status (t.ex. OK, Avbryt, etc).

förfrågningskoden används av källaktiviteten för att veta vilken destinationsaktivitet som returnerar samtalet.

vi kunde se att destinationsaktiviteten inte har någon synlighet för förfrågningskoden.

odokumenterad startActivityForResult Fragment Flow

i Fragment har vi också startActivityForResult-funktionen att ringa, och även onActivityResult-funktionen att åsidosätta.

detta väcker flera frågor…t. ex. hur fungerar det? Är det samma sak som aktivitetens startactivity forresult och onactivity result? Hur är de relaterade?
det korta svaret är, de är liknande men subtilt olika. En vanlig orsak till förvirring och bugg. Så det är viktigt att förstå likheten och skillnaderna.

fragmentflödet illustreras.

nedan är diagrammet illustrerar tydligt hur det hela fungerar tillsammans. Skillnaderna med activity ’ s startActivityForResult och onActivityResult flow är färgade i rött.

Låt oss mer utarbeta det.

när vi kallar Fragment startActivityForResult (Obs: inte aktivitet?.startActivityForResult) är skapandet av destinationsaktivitet detsamma. Skillnaden är dock onactivityresultat.

startActivityForResult() måste hantera det från fragment onActivityForResult()

getActivity().startActivityForResult() måste hantera det från activity’sonActivityForResult()

om du är på en fragment och du vill hantera resultatet på fragment, använd onActivityForResult(), annars, om du vill hantera det från activity av fragmentet, användgetActivity.startActivityForResult()

när Android SDK returnerar onActivityResult, har förfrågningskoden ändrats. En 0xP0000 läggs till den ursprungliga requestCode.

p-värdet börjar från 1 och ökas för varje onActivityResult anropas från samma målfragment. (Om ett annat målfragment anropas återställs P-värdet).

t.ex. om den ursprungliga requestCode är 0xFF (dvs 255), kommer requestCode retur första gången vara 0x100FF. Andra gången returförfrågankoden kommer att vara 0x200FF.

vid återgång till källaktivitetens onActivityResult förväntas det att det ska ringa super.onActivityResult, som finns i FragmentActivity (föräldern till AppCompatActivity)

onActivityResult i FragmentActivity extraherar sedan p-värdet (med requestCode >> 16). P är indexet för matrisen där källfragmentet lagras. (t. ex. om requestCode är 0x200FF, då 0x200FF >> 16 = 2)

med hjälp av p-värdet har det nu tillgång till källfragmentet, som används i steg 9 nedan.

nu tar det bort p-värdet från requestCode (med requestCode & 0xffff) för att komma tillbaka till den ursprungliga request-koden (t. ex. om requestCode är 0x200FF, då 0x200FF & 0xFFFF = 0xff)

som nu får den ursprungliga förfrågningskoden som källfragmentet skapade, kan det ringa källfragmentets onActivityResult med den ursprungliga förfrågningskoden.

några grundläggande punkter som vill veta.

A. beteendet hos aktivitetens startActivityForResult skiljer sig från Fragment startActivityForResult

i Fragment, om vi kallar activity?.startActivityForResult(...), kommer Fragment ’ s onActivityResult inte att anropas automatiskt.

B. Om vi åsidosätter aktivitetens onActivityResult, se till att vi har super.onActivityResult på plats

om vi åsidosätter källaktivitetens onActivityResult, men glömmer att ha super.onActivityResult kommer fragmentets onActivityResult inte att anropas.

C. förfrågningskoden som ses i aktivitetens onActivityResult skiljer sig från det enda fragmentet som tillhandahålls

på grund av anledningen till att Android SDK bifogade P till requestCode, i aktivitetens onActivityResult får vi aldrig samma requestCode där. Detta orsakar ibland förvirring för utvecklaren vid felsökning av koden där.

D. När en aktivitet återställs från staten (dvs. onStateInstance != null), bör det undvika att återskapa sitt fragment.

när onActivityResult anropas försökte den hämta det ursprungliga fragmentet. Detta utförs också för den aktivitet som återställs från ett dödat tillstånd (t.ex. emulerad med Don ’ t Keep Activity).

så om utvecklaren återskapar fragmentet varje gång onCreate kallas (oavsett om det är ett återställt tillstånd eller inte), kommer det ursprungliga fragmentet som återställdes att förstöras, och onActivityResult av den som ringer, kommer fragmentet mystiskt inte att ringas.

Detta är en fallgrop även för många erfarna utvecklare och app släpptes i fältet, eftersom det är mycket svårt att en identifierad bugg (eftersom det inte händer varje gång, och kräver en mer komplex flöde för att utlösa).

Tack för att du läste …