Lekce 6 - Android Intenty a aktivity - Java kód SumResultActivity
Minule, v lekci Android Intenty a aktivity - SumResultActivity, jsme vytvořili XML návrh GUI aktivity
SumResultActivity
, přijímající z aktivity
SumActivity
dvě čísla.
Celá dnešní lekce bude, jak asi tušíte, o Java kódu
SumResultActivity
.
Java kód
SumResultActivity
Upravíme si jej tedy do následující podoby, kterou si hned podrobně vysvětlíme:
public class SumResultActivity extends AppCompatActivity { TextView labelNumber1; TextView labelNumber2; TextView labelResult; Button btnSend; int number1 = 0; int number2 = 0; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.sum_result_activity); setTitle(R.string.sum_result_activity_title); labelNumber1 = findViewById(R.id.labelNumber1); labelNumber2 = findViewById(R.id.labelNumber2); labelResult = findViewById(R.id.labelResult); btnSend = findViewById(R.id.btnSend); btnSend.setOnClickListener(clickListener); try { Intent incomingIntent = getIntent(); number1 = incomingIntent.getIntExtra("number_1", 0); number2 = incomingIntent.getIntExtra("number_2", 0); labelNumber1.setText("" + number1); labelNumber2.setText("" + number2); labelResult.setText("" + (number1 + number2)); } catch (NullPointerException e) { labelNumber1.setText("?"); labelNumber2.setText("?"); Toast.makeText(this, R.string.incoming_intent_data_error, Toast.LENGTH_LONG).show(); } } }
Chybějící proměnnou clickListener
si doplníme
za chvíli.
Máme zde připravené atributy pro jednotlivé komponenty aktivity, které
si inicializujeme v onCreate()
. Také zde máme atributy pro
uchování 2 čísel, která ale byla zadána v předchozí aktivitě.
Dostáváme se k oné zajímavé části.
Příjem dat z aktivity
SumActivity
V každé aktivitě získáme voláním getIntent()
intent,
kterým byla daná aktivita otevřena. My toto provádíme v metodě
onCreate()
a intent ukládáme do proměnné
incomingIntent
. Z ní pak pomocí klíčů získáme naše čísla
určená k součtu. Zadáváme samozřejmě ty klíče, pod které jsme si data
uložili v SumActivity
.
Získané hodnoty pak zobrazujeme ve dvou TextView
a ve třetím
zobrazujeme jejich součet. Celý popsaný postup je v bloku try
-
catch
, kterým odchytáváme případnou výjimku
NullPointerException
. Tato výjimka bude vyvolána v případě,
že "příchozí" intent, uložený do proměnné incomingIntent
,
bude obsahovat hodnotu null
. Ve chvíli, kdy bychom na proměnné
incomingIntent
, s hodnotou null
, zavolali metodu
getIntExtra()
, došlo by bez ošetření výjimky k pádu aplikace
za běhu.
Událost kliknutí na tlačítko
Máme zde také další slíbený alternativní způsob obsluhy kliknutí na tlačítko.
Odeslání výsledku součtu zpět do SumActivity
je
realizováno opět Java kódem, podobně jako v SumActivity
.
Tenkrát jsme tlačítku přiřadili inline zápisem
OnClickListener
vytvořením anonymní
třídy. Říkali jsme si, že tento přístup neumožňuje opětovné
použití kódu. Zde bude postup podobný. Rozdíl bude v tom, že vytvoříme
instanci listeneru, kterou lze přiřadit libovolnému počtu elementů.
Do kódu za deklaraci proměnných přidáme:
View.OnClickListener clickListener = new View.OnClickListener() { @Override public void onClick(View v) { if (v.getId() == R.id.btnSend) { Intent resultIntent = new Intent(); resultIntent.putExtra("result_from_activity_sum", number1 + number2); setResult(RESULT_OK, resultIntent); finish(); } } };
Tento listener v metodě onCreate()
nastavujeme jedinému
tlačítku. Listener povinně přepisuje metodu onClick()
, která
je volána s parametrem typu View
. Toto View
je
referencí na element, který byl v GUI stisknut.
V metodě onClick()
pak už jen testujeme, zda se ID
stisknutého elementu rovná ID tlačítka pro odeslání odpovědi (tedy zda
událost kliknutí vyvolalo toto tlačítko).
Protože jsme tento listener přiřadili pouze jedinému objektu, není tato podmínka ani nutná, protože jiná možnost nastat nemůže. Je ji ovšem vhodné uvést, protože když bychom někdy přidali nějaký další klikací prvek, mohli bychom na ni zapomenout a takové chyby se špatně hledají
Při porovnání tohoto způsobu obsluhy události s anonymní třídou v
SumActivity
je zřejmé, že tento má výhodu ve své
znovupoužitelnosti. Ale stále má nevýhodu ve větším množství a menší
přehlednosti, než u způsobu s atributem android:onClick
přímo
v XML.
Odeslání odpovědi do
SumActivity
Po kliknutí se chceme vrátit do předchozí aktivity a poslat do ni
výsledek. Popsaný OnClickListener
v metodě
onClick()
tedy vytváří intent, který neobsahuje žádnou akci.
Zde totiž vytváříme intent pouze za účelem přenosu dat mezi aktivitami. V
dalším řádku intentu tato data nastavujeme s klíčem z textového
řetězce. Díky tomuto klíči data vyzvedneme v SumActivity
, kam
je pošleme.
Dalším řádkem voláme metodu setResult()
. Minule jsme si v
této souvislosti popisovali dvě konstanty:
RESULT_OK
aRESULT_CANCELED
.
Druhým parametrem je vytvořený intent s daty pro
SumActivity
.
Posledním řádkem aktivitu SumResultActivity
zavřeme a
vrátíme se zpět do SumActivity
.
Deklarace aktivit v
AndroidManifest.xml
I přes to, že zatím nemáme dokončenou deklaraci metody
sendData()
v aktivitě SumActivity
, je možné naší
aplikaci Activities
spustit. Pokud tak učiníme a pokusíme se
otevřít prvním tlačítkem SumActivity
, dojde k pádu aplikace s
výjimkou ActivityNotFoundException
. V Android Studiu, pohledem do
logcatu, uvidíme s nastaveným filtrem na zobrazení errorů něco
takového:
Ve výpisu logcatu je dokonce upozornění na to, že aktivita není
deklarována v souboru manifestu. Otevřeme tedy soubor
AndroidManifest.xml
:
Na obrázku je vidět obsah tohoto souboru po jeho automatickém vygenerování Android Studiem při vytvoření nového projektu. Do této chvíle nebylo nutné tento soubor jakkoliv upravovat.
Po přidání jakékoliv další aktivity do projektu je nutné ji v manifestu deklarovat!
My jsme vytvořili aktivity SumActivity
a
SumResultActivity
. Obě tedy do manifestu přidáme následujícím
kódem za deklaraci MainActivity
:
<activity android:name=".SumActivity" android:parentActivityName=".MainActivity"> </activity> <activity android:name=".SumResultActivity" android:parentActivityName=".MainActivity"> </activity>
Upravený soubor AndroidManifest.xml
bude tedy vypadat
takto:
parentActivityName
Atribut android:parentActivityName=".MainActivity"
není
povinný. Slouží pro zobrazení šipky v levé části toolbaru aktivity. Tato
šipka slouží pro navigaci zpět do té aktivity, která je uvedena v hodnotě
atributu. Následující obrázky ukazují rozdíl - první zobrazuje stav bez
parametru a druhý s parametrem:
Všimněte si že v kódu manifestu z SumResultActivity
se touto
šipkou vracíme přímo do hlavní aktivity a ne do
SumActivity
.
V příští lekci, Android Intenty a aktivity - Zobrazení SumResultActivity, si napíšeme kód pro zobrazení aktivity
SumActivity
. V aktivitě SumResultActivity
se
naučíme používat odkazy na textové řetězce.