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 …