17. diel - Android Intenty a aktivity - Odpoveď od zatvorenej aktivity
V minulej lekcii, Android Intent a aktivity - Java kód aktivity ShareActivity , sme si ukázali zdieľanie zadaného textu do iných aplikácií a otváranie aplikácií schopných zobraziť webovú adresu.
V dnešnom Android tutoriále si ukážeme, ako otvoriť aktivitu tak, aby nám, po svojom ukončení, odovzdala odpoveď s požadovanými dátami.
Často v aplikácii otvárame inú aktivitu, od ktorej, po jej
zatvorení, očakávame odpoveď. V našom konkrétnom prípade budeme
z aktivity SumActivity
otvárať aktivitu
SumResultActivity
, ktorá odovzdá späť do aktivity
SumActivity
výsledok súčtu dvoch čísel.
To, či zatvorená aktivita bude alebo nebude odovzdávať dáta späť, záleží na spôsobe, akým je otvorená. Postupne sa dostaneme k dvom možným spôsobom otvorenia aktivity:
- bez požiadavky odpovede po jej zatvorení,
- s očakávaním odpovede po jej zatvorení.
Najskôr si v aktivite SumActivity
, na ktorej stále pracujeme,
napíšeme kód pre príjem súčtu dvoch čísel, ktorý tu
budeme očakávať po zatvorení aktivity SumResultActivity
.
Na otvorenie aktivity, vracajúcej späť dáta, existujú dva postupy. Prvý, doteraz používaný, je teraz v dokumentácii označený ako zastaraný. Druhý novší spôsob nahrádza ten prvý. Ako dôvod tejto zmeny oficiálna dokumentácia uvádza efektívnejšiu prácu s pamäťou. Obe možnosti si vysvetlíme.
Starší spôsob získania odpovede
Aktivita, ktorá očakáva odpoveď od inej aktivity, prepisuje metóduonActivityResult()
z triedy Activity
.
Metóda onActivityResult()
Metóda onActivityResult()
patrí triede Activity
. My
si ju pridáme do našej triedy SumActivity
:
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { if (requestCode == 1) { if (data != null) { if (data.hasExtra("result_from_activity_sum")) { labelResult.setText("" + data.getIntExtra("result_from_activity_sum", -1)); } else { labelResult.setText(R.string.info_error_loading_result); } } } } else if (resultCode == RESULT_CANCELED) { labelResult.setText(R.string.info_no_result); } }
Po zatvorení aktivity SumResultActivity
dostane
aktivita SumActivity
zo zatvorenej aktivity
SumResultActivity
odpoveď zavolaním jej metódy
onActivityResult()
.
Metóda onActivityResult()
prijíma tri parametre:
requestCode
- Hodnota parametrarequestCode
z volania metódystartActivityForResult()
.resultCode
- Hodnota typuint
hovoriaci akým spôsobom bola zatvorená aktivita ukončená. Číselná hodnota je vyjadrená konštantou:RESULT_OK
v prípade, že v zatvorenej aktivite bolo, pred jej ukončením,setResult(RESULT_OK, resultIntent)
.RESULT_CANCELED
dostaneme, ak bola aktivita ukončená volanímsetResult(RESULT_CANCELED)
alebo tlačidlom Späť. Toto bude čoskoro bližšie vysvetlené pri popise aktivitySumResultActivity
.RESULT_OK
v prípade, že v zatvorenej aktivite bolo, pred jej ukončením,setResult(RESULT_OK, resultIntent)
.RESULT_CANCELED
dostaneme, ak bola aktivita ukončená volanímsetResult(RESULT_CANCELED)
alebo tlačidlom Späť. Toto bude čoskoro bližšie vysvetlené pri popise aktivitySumResultActivity
.data
- Objekt triedyIntent
vložený do parametra volaniasetResult(RESULT_OK, resultIntent)
v zatváranej aktivite. Tým sa dostávame na použitie intentu ako kontajnera primitívnych dát. V intente bez akcie nájdeme dáta odoslané aktivitouSumResultActivity
. Popis, ako tieto dáta vytvoriť, opäť uvidíme vo výklade o aktiviteSumResultActivity
.
V metóde onActivityResult()
podmienkou zisťujeme, ako bola
aktivita zatvorená. Pokiaľ parameter resultCode
obsahuje hodnotu
RESULT_OK
, ďalší postup určujeme podľa
int requestCode
. My tu máme iba jedinú možnosť.
Ďalej v podmienke testujeme, či prichádzajúci intent
obsahuje nejaké návratové dáta. Očakávame, že nám bude
vrátený súčet dvoch čísel, odoslaných do
SumResultActivity
. Pokiaľ je podmienka splnená, zisťujeme
volaním data.hasExtra()
, či dáta obsahujú uvedené
kľúče, vyjadreným textovým reťazcom. Pod týmto kľúčom
sú dáta do návratového intentu vložené v SumResultActivity
.
Pokiaľ dáta tieto kľúče obsahujú, rovno nastavujeme TextView
,
ktorý je určený pre zobrazenie výsledku súčtu v
SumActivity
.
Nový spôsob získania odpovede
V novom postupe aktivita, ktorá očakáva odpoveď od inej aktivity, neprepisuje metóduonActivityResult()
z triedy
Activity
.
Namiesto toho použijeme triedu ActivityResultLauncher
, ktorej
inštanciu získame zavolaním metódy registerForActivityResult()
.
Táto metóda vo svojich parametroch prijíma rozhranie
ActivityResultCallback
, v ktorého prepísanej metóde
onActivityResult()
získavame odpoveď zo zatvorenej
aktivity.
Pozor na zhodný názov dvoch rozdielnych metód! V
starom spôsobe prepisuje trieda, otvárajúca
iné aktivity, metódu onActivityResult()
, patriacu triede
Activity
. Aj v novom spôsobe prepisujeme metódu
onActivityResult()
, ale úplne inde - v tomto prípade táto
metóda patrí rozhraniu ActivityResultCallback
.
Ide o zhodný názov dvoch rôznych metód.
Trieda SumActivity
V triede SumActivity
, pod deklaráciu premenných, pridáme tento
kód:
ActivityResultLauncher<Intent> sumActivityResultLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { if (result.getResultCode() == Activity.RESULT_OK) { Intent data = result.getData(); if (data != null) { if (data.hasExtra("result_from_activity_sum")) { labelResult.setText("" + data.getIntExtra("result_from_activity_sum", -1)); } else { labelResult.setText(R.string.info_error_loading_result); } } } } });
V uvedenom kóde vytvárame inštanciu triedy
ActivityResultLauncher
volaním metódy
registerForActivityResult()
.
Metóda registerForActivityResult()
patrí
rozhranie ActivityResultCaller
, ktoré je súčasťou API nového
spôsobu otvárania aktivít vracajúcich odpoveď.
V druhom parametri metódy deklarujeme rozhranie
ActivityResultCallback
, v ktorého prepísanej metóde
onActivityResult()
získavame odpoveď od zatvorenej
aktivity. Na inštancii result
typu
ActivityResult
voláme metódu getData()
, ktorá nám
vracia objekt typu Intent
. S objektom Intent
ďalej
pracujeme úplne rovnako ako vo vyššie popísanom starom spôsobe.