înțelegeți comportamentul startActivityForResult pentru Fragment și activitate

întregul startActivityForResult și onActivityResult este permis o comunicare 2-way între activitatea sursă și activitatea de destinație. Fluxul său este așa cum se arată în diagrama de mai jos.

din fluxul de mai jos, putem înțelege cu ușurință fluxul OnActivityResult de la activitatea sursă la activitatea de destinație

apelul de activitate sursă, startActivityForResult prin trimiterea în intenția împreună cu codul de cerere pentru Android SDK.

Android SDK deschide apoi activitatea în consecință, așa cum se menționează în intenție.
odată ce activitatea de destinație și-a terminat activitatea, aceasta revine la activitatea apelantului.

s-ar putea trimite rezultatul înapoi folosind setResult prin trimiterea în resultCode și intenția

mai multe note aici:

resultCode este utilizat de către activitatea de destinație pentru a semnaliza activitatea sursă ceea ce este starea (de exemplu, OK, anula, etc).

codul de solicitare este utilizat de activitatea sursă pentru a ști ce activitate de destinație returnează apelul.

am putut vedea că activitatea de destinație nu are vizibilitate a codului de solicitare.

flux fragment Startactivityforresult nedocumentat

în Fragment, avem, de asemenea, funcția startActivityForResult pentru a apela, și, de asemenea, funcția onActivityResult pentru a trece peste.

acest lucru ridică mai multe întrebări…de exemplu, cum funcționează? Este la fel ca startActivityForResult activității și onActivityResult? Cum sunt legate?
răspunsul scurt este că sunt similare, dar subtil diferite. O cauză frecventă de confuzie și bug. Deci, este important să înțelegem asemănarea și diferențele.

fluxul fragmentului ilustrat.

mai jos este diagrama ilustrează în mod clar modul în care toate funcționează împreună. Diferențele cu activity ‘ s startActivityForResult și onactivityresult flow sunt colorate în roșu.

să mai elaborăm.

când numim startActivityForResult Fragment (Notă: Nu activitate?.startActivityForResult), crearea activității de destinație este aceeași. Cu toate acestea, diferența este onactivitatearezultat.

startActivityForResult() trebuie să se ocupe de fragment onActivityForResult()

getActivity().startActivityForResult() trebuie să se ocupe de la activity‘s onActivityForResult()

dacă sunteți pe un fragment și doriți să se ocupe de rezultatul pe fragment, utilizați onActivityForResult(), în caz contrar, dacă doriți să se ocupe de la activity a fragmentului, utilizați getActivity.startActivityForResult()

când Android SDK returnează onActivityResult, codul de cerere a fost modificat. Un 0xp0000 este anexat la requestCode original.

valoarea P începe de la 1 și incrementată pentru fiecare onActivityResult este apelată din același fragment de destinație. (Dacă se numește un alt Fragment de destinație, valoarea P este resetată).

de exemplu, dacă codul original de solicitare este 0xFF (adică 255), codul de solicitare returnat prima dată va fi 0x100FF. A doua cerere de returnarecodul va fi 0x200FF.

la revenirea la onActivityResult activitatea sursei, este de așteptat ca acesta ar trebui să sune super.onActivityResult, care se află în FragmentActivity (părintele AppCompatActivity)

onActivityResult în FragmentActivity va extrage apoi valoarea P (folosind requestCode >> 16). P este indicele matricei în care este stocat fragmentul sursă. (de exemplu, dacă requestCode este 0x200FF, apoi 0x200FF >> 16 = 2)

folosind valoarea P, acum are acces la fragmentul sursă, care este utilizat la PASUL 9 de mai jos.

acum, elimină valoarea P din codul de solicitare (folosind codul de solicitare & 0xffff), pentru a reveni la codul de solicitare inițial (de ex. dacă requestCode este 0x200FF, apoi 0x200FF & 0xffff = 0xFF)

ca acum devine codul de cerere original care fragmentul sursă creat, s-ar putea apela onactivityresult fragmentului sursă cu codul de cerere original.

câteva puncte de bază care vor să știe.

A. comportamentul startActivityForResult al activității este diferit de Startactivityforresult al fragmentului

în Fragment, dacă numim activity?.startActivityForResult(...), atunci onActivityResult al fragmentului nu va fi apelat automat.

B. Dacă vom suprascrie onactivityresult activitate, asigurați-vă că avem super.onActivityResult în loc

dacă vom suprascrie sursa de activitate onActivityResult, dar uitați să aibă super.onActivityResult apoi Fragment onActivityResult nu va fi numit.

C. requestCode văzut în onActivityResult activitate este diferit de un fragment furnizat

din cauza motiv, Android SDK anexat P la requestCode, în activitatea de onActivityResult, nu vom primi identic requestCode acolo. Acest lucru uneori provoacă confuzie dezvoltatorului atunci când depanează codul acolo.

D. Când o activitate este restabilită din stat (adică onStateInstance != null), ar trebui să evite recrea fragmentul său.

când se numește onActivityResult, a încercat să recupereze fragmentul original. Acest lucru se realizează și pentru activitatea care este restabilită dintr-o stare ucisă (de exemplu, emulată folosind Nu păstrați activitatea).

deci, dacă dezvoltatorul recreează fragmentul de fiecare dată când onCreate este apelat (indiferent dacă este o stare restaurată sau nu), atunci fragmentul original care a fost restaurat va fi distrus și onActivityResult al apelantului, fragmentul nu va fi apelat în mod misterios.

aceasta este o capcană chiar și pentru mulți dezvoltatori cu experiență și app lansat în domeniu, deoarece este foarte greu de un bug identificat (deoarece nu se întâmplă de fiecare dată, și necesită un flux mai complex pentru a declanșa).

Vă mulțumim pentru lectură …