Lekce 4 - Android Intenty a aktivity - Odpověď od zavřené aktivity
V předchozím kvízu, Kvíz - Nastavení vzhledu aktivity a intenty v Androidu, jsme si ověřili nabyté zkušenosti z předchozích lekcí.
V dnešním Android tutoriálu si ukážeme, jak otevřít aktivitu tak, aby nám, po svém ukončení, předala odpověď s požadovanými daty.
Často v aplikaci otevíráme jinou aktivitu, od které, po jejím
zavření, očekáváme odpověď. V našem konkrétním případě
budeme z aktivity SumActivity
otevírat aktivitu
SumResultActivity
, která předá zpět do aktivity
SumActivity
výsledek součtu dvou čísel.
To, zda zavřená aktivita bude nebo nebude předávat data zpět, záleží na způsobu, jakým je otevřena. Postupně se dostaneme ke dvěma možným způsobům otevření aktivity:
- bez požadavku odpovědi po jejím zavření,
- s očekáváním odpovědi po jejím zavření.
Nejdříve si v aktivitě SumActivity
, na které stále
pracujeme, napíšeme kód pro příjem součtu dvou čísel,
který zde budeme očekávat po zavření aktivity
SumResultActivity
.
K otevření aktivity, vracející zpět data, existují dva postupy. První, dosud používaný, je nyní v dokumentaci označen jako zastaralý. Druhý novější způsob nahrazuje ten první. Jako důvod této změny oficiální dokumentace uvádí efektivnější práci s pamětí. Obě možnosti si vysvětlíme.
Starší způsob získání odpovědi
Aktivita, která očekává odpověď od jiné aktivity, přepisuje metodu
onActivityResult()
ze třídy Activity
.
Metoda onActivityResult()
Metoda onActivityResult()
patří třídě
Activity
. My si ji přidáme do naší třídy
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 { labelResult.setText(R.string.info_no_result); } }
Po zavření aktivity SumResultActivity
obdrží
aktivita SumActivity
ze zavřené aktivity
SumResultActivity
odpověď zavoláním její metody
onActivityResult()
.
Metoda onActivityResult()
přijímá tři parametry:
requestCode
- Hodnota parametrurequestCode
z volání metodystartActivityForResult()
.resultCode
- Hodnota typuint
říkající jakým způsobem byla zavřená aktivita ukončena. Číselná hodnota je vyjádřena konstantou:RESULT_OK
v případě, že v zavřené aktivitě bylo, před jejím ukončením, zavolánosetResult(RESULT_OK, resultIntent)
.RESULT_CANCELED
obdržíme, pokud byla aktivita ukončena volánímsetResult(RESULT_CANCELED)
nebo tlačítkem Zpět. Toto bude brzy blíže vysvětleno při popisu aktivitySumResultActivity
.
data
- Objekt třídyIntent
vložený do parametru volánísetResult(RESULT_OK, resultIntent)
v zavírané aktivitě. Tím se dostáváme k použití intentu jako kontejneru primitivních dat. V intentu bez akce nalezneme data odeslaná aktivitouSumResultActivity
. Popis, jak tato data vytvořit, opět uvidíme ve výkladu o aktivitěSumResultActivity
.
V metodě onActivityResult()
podmínkou zjišťujeme, jak byla
aktivita zavřena. Pokud parametr resultCode
obsahuje hodnotu
RESULT_OK
, další postup určujeme podle
int requestCode
. My zde máme pouze jedinou možnost.
Dále v podmínce testujeme, zda příchozí intent obsahuje
nějaká návratová data. Očekáváme, že nám bude vrácen
součet dvou čísel, odeslaných do
SumResultActivity
. Pokud je podmínka splněna, zjišťujeme
voláním data.hasExtra()
, zda data obsahují uvedené
klíče, vyjádřeným textovým řetězcem. Pod tímto
klíčem jsou data do návratového intentu vložena v
SumResultActivity
. Pokud data tyto klíče obsahují, rovnou
nastavujeme TextView
, který je určen pro zobrazení výsledku
součtu v SumActivity
.
Nový způsob získání odpovědi
V novém postupu aktivita, která očekává odpověď od jiné aktivity,
nepřepisuje metodu onActivityResult()
ze třídy
Activity
.
Místo toho použijeme třídu ActivityResultLauncher
, jejíž
instanci získáme zavoláním metody registerForActivityResult()
.
Tato metoda ve svých parametrech přijímá rozhraní
ActivityResultCallback
, v jehož přepsané metodě
onActivityResult()
získáváme odpověď ze zavřené
aktivity.
Pozor na shodný název dvou rozdílných metod! Ve
starém způsobu přepisuje třída,
otevírající jiné aktivity, metodu onActivityResult()
,
patřící třídě Activity
. I v novém způsobu
přepisujeme metodu onActivityResult()
, ale úplně jinde - v tomto
případě tato metoda patří rozhraní
ActivityResultCallback
. Jde o shodný název dvou různých
metod.
Třída SumActivity
Ve třídě SumActivity
, pod deklaraci proměnných, přidá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 uvedeném kódu vytváříme instanci třídy
ActivityResultLauncher
voláním metody
registerForActivityResult()
.
Metoda registerForActivityResult()
patří
rozhraní ActivityResultCaller
, které je součástí API nového
způsobu otevírání aktivit vracejících odpověď.
Ve druhém parametru metody deklarujeme rozhraní
ActivityResultCallback
, v jehož přepsané metodě
onActivityResult()
získáváme odpověď od zavřené
aktivity. Na instanci result
typu
ActivityResult
voláme metodu getData()
, která nám
vrací objekt typu Intent
. S objektem Intent
dále
pracujeme úplně stejně jako ve výše popsaném starém způsobu.
V příští lekci, Android Intenty a aktivity - SumResultActivity, vytvoříme vzhled grafického uživatelského rozhraní aktivity, do které budeme odesílat uživatelem zadaná čísla, určená k součtu.