C týden
Tento týden až 80% sleva na e-learning týkající se jazyka C
50 % bodů zdarma na online výuku díky naší Slevové akci!

Lekce 3 - Android Intenty a aktivity - Aktivita A - Java kód

V minulé lekci, Android Intenty a aktivity - Aktivita A - Součet čísel, jsme si připravili GUI aktivity pro součet 2 čísel.

Než začneme psát Java kód ActivityA, vytvoříme rozhraní pro deklarace všech konstant ukázkové aplikace Activities.

V aplikaci máme totiž několik aktivit a nechceme každé definovat konstanty zvlášť. Některé budou určitě potřebovat ty samé. Proto je definujeme centrálně v jednom rozhraní.

Rozhraní pro konstanty

Ve struktuře projektu klikneme pravým tlačítkem na složku (viz. obrázek) a v menu přes New na Java Class:

V otevřeném okně New Java Class do řádku Name napíšeme AppConstants, v dalším řádku Kind vybereme možnost Interface a potvrdíme tlačítkem OK:

Bude vytvořen soubor AppConstants.java:

public interface AppConstants {

}

Do tohoto souboru budeme postupně přidávat konstanty, použité v projektu.

Konstanta LOG_TAG

Hned přidáme konstantu pro tag zpráv Logcatu:

public interface AppConstants {
    String LOG_TAG = "Activities_log_tag";
}

Takto můžeme pak snadno poznat naše logy.

Přístup ke konstantám

Přístup ke konstantám je možný dvěma způsoby. První způsob je přímo, například voláním:

String tag = AppConstants.LOG_TAG;
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Nebo může třída, ve které konstantu potřebujeme, implementovat rozhraní AppConstants, čímž získá přístup ke všem jeho konstantám:

public class MyClass implements AppConstants {
    String tag = LOG_TAG;
}

ActivityA.java

Vraťme se zpět k aktivitě ActivityA. Nyní upravíme její Java kód na následující:

public class ActivityA extends AppCompatActivity {

    EditText etNumber1, etNumber2;
    Button btnSend;
    TextView labelResult;

    int number1, number2;


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_a);
        setTitle(R.string.activity_a_title);

        etNumber1 = findViewById(R.id.etNumber1);
        etNumber2 = findViewById(R.id.etNumber2);
        labelResult = findViewById(R.id.labelResult);
        btnSend = findViewById(R.id.btnSend);

        btnSend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    number1 = Integer.parseInt(etNumber1.getText().toString());
                    number2 = Integer.parseInt(etNumber2.getText().toString());
                    sendData();
                } catch (NumberFormatException e) {
                    Log.d(AppConstants.LOG_TAG, "NumberFormatException");
                    Log.d(AppConstants.LOG_TAG, e.getMessage());
                    showErrorToast();
                } catch (NullPointerException e) {
                    Log.d(AppConstants.LOG_TAG, "NullPointerException");
                    Log.d(AppConstants.LOG_TAG, e.getMessage());
                    showErrorToast();
                }
            }
        });
    }

    private void showErrorToast() {
        Toast.makeText(this, R.string.info_incorrect_entry, Toast.LENGTH_LONG).show();
    }

}

Pojďme si jej vysvětlit:

Kliknutí na tlačítko

V ActivityMain.java jsme události kliknutí nastavili příslušnými parametry tlačítek v XML a deklarací obslužné metody v Java kódu. Zde to děláme pro změnu pouze Java kódem, přesněji přiřazením OnClickListener komponentám, na kterých budeme kliknutí očekávat. Nastavení listeneru zde provádíme inline anonymní třídou. Na tomto přístupu není nic špatného, ale má nevýhodu ve větším množství Java kódu a v nemožnosti kód znovu použít.

Kliknutím na tlačítko Odeslat k výpočtu zadaná čísla odesíláme do aktivity ActivitySum, jejímž úkolem je čísla sečíst a výsledek odeslat zpět do aktivity ActivityA. Zadání uživatele v políčkách EditText převádíme z typu String na typ int voláním metody parseInt() třídy Integer.

Během konverze může, v případě, že zadaný text obsahuje znak, který není číslicí, dojít k výjimce NumberFormatException. To je první ze dvou důvodů, proč je tato část kódu "zabalena" do bloku try - catch. Druhým důvodem je fakt, že řádek etNumberOne.getText().toString() může vyvolat výjimku NullPointerException. Zmíněné případné výjimky tedy odchytáváme a můžeme na ně reagovat, aniž by došlo k pádu aplikace.

Otevření aktivity pro součet zadaných čísel

Po úspěšné konverzi vstupu voláme metodu sendData(). Přidejme si do třídy i její kód:

private void sendData() {
    Intent sendIntent = new Intent(this, ActivitySum.class);
    sendIntent.putExtra("number_1", number1);
    sendIntent.putExtra("number_2", number2);
    startActivityForResult(sendIntent, 1);
}

Na prvním řádku vytváříme explicitní intent, vyjadřující konkrétní záměr - spustit ActivitySum.class. Tuto aktivitu zatím nemáme vytvořenou, což brzy napravíme! Jde o aktivitu, která bude zadaná čísla sčítat.

V následujících dvou řádcích přiřazujeme data se zadanými čísly. Každé číslo do intentu vkládáme s klíčem, tvořeným textovým řetězcem. Díky klíčům si čísla "vyzvedneme" v aktivitě, kterou intentem otevřeme.

Posledním řádkem voláme metodu startActivityForResult(), čímž aktivitu ActivitySum otevřeme s tím, že po jejím zavření budeme v aktivitě ActivityA očekávat odpověď s výsledkem součtu. Ta přijímá dva parametry:

  • vytvořený intent
  • requestCode - jde o hodnotu typu int, označující důvod skoku z aktivity ActivityA do jiné aktivity.

requestCode

Kdykoliv otevřeme jinou aktivitu voláním startActivityForResult(), bude po jejím zavření původní aktivitě volána metoda onActivityResult(), kterou si hned uvedeme. Volání této metody upozorňuje na zavření aktivity, ale neříká, o jakou aktivitu šlo, nic o důvodu jejího otevření a jaká data máme očekávat. Právě díky requestCode po přijetí odpovědi víme, jaká aktivita byla otevřena a následně zavřena a tím pádem i jak na odpověď reagovat, nebo jaká data v odpovědi očekávat.

Může se i stát, že sice víme, která aktivita byla zavřena (např. proto, že jinou aktivitu ani neotevíráme), ale tato aktivita může mít schopnost plnit více různých úkolů s různými typy návratových dat. Díky requestCode pak víme, jaký úkol byl proveden, tedy jaká data v odpovědi očekávat a jak je zpracovat.

startActivityForResult()

Metodu pro odpověď s výsledkem aktivity si teď přidejme:

@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 zavření aktivity ActivitySum obdrží z této aktivity ActivityA odpověď voláním její metody onActivityResult(). S touto metodou získáme tři parametry:

  • requestCode - Zde bude vrácena hodnota parametru requestCode z volání metody startActivityForResult().
  • resultCode - Hodnota typu int, která říká, 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áno setResult(RESULT_OK, resultIntent).
    • RESULT_CANCELED obdržíme, pokud byla aktivita ukončena voláním setResult(RESULT_CANCELED) nebo tlačítkem Zpět. Toto bude brzy blíže vysvětleno při popisu aktivity ActivitySum.
  • data - Zde nalezneme objekt třídy Intent, 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á aktivitou ActivitySum. Popis, jak tato data vytvořit, opět uvidíme ve výkladu o aktivitě ActivitySum.

V metodě onActivityResult() jako první 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 ActivitySum. 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 ActivitySum. Pokud data tyto klíče obsahují, rovnou nastavujeme TextView, který je určen pro zobrazení výsledku součtu v ActivityA.

V příští lekci, Android Intenty a aktivity - ActivitySum, vytvoříme vzhled grafického uživatelského rozhraní aktivity, do které budeme odesílat uživatelem zadaná čísla, určená k součtu.


 

Předchozí článek
Android Intenty a aktivity - Aktivita A - Součet čísel
Všechny články v sekci
Android Intenty a aktivity
Článek pro vás napsal lupa.lupa
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
Aktivity (2)

 

 

Komentáře

Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zatím nikdo nevložil komentář - buď první!