Jak používat životní cyklus a stav aktivity,Jak používat životní cyklus a stav aktivity

1. Vítejte

Tato praktická kódová laboratoř je součástí Unit 1: Začínáme v kurzu Android Developer Fundamentals (verze 2). Největší hodnotu z tohoto kurzu získáte, pokud budete postupně procházet kódovými laboratořemi:

  • Úplný seznam kódových laboratoří v kurzu najdete v článku Codelabs for Android Developer Fundamentals (V2).
  • Podrobnosti o kurzu, včetně odkazů na všechny koncepční kapitoly, aplikace a snímky, najdete v tématu Android Developer Fundamentals (verze 2).

Zavedení

V tomto praktickém cvičení se dozvíte více o životním cyklu aktivity. Životní cyklus je sada stavů, ve kterých může být aktivita během celé své životnosti, od okamžiku, kdy byla vytvořena, do doby, kdy je zničena a systém získává zpět své zdroje. Když uživatel přechází mezi aktivitami ve vaší aplikaci (a také do a z aplikace), aktivity přecházejí mezi různými stavy v jejich životních cyklech.

Dvojité potíže

Každá fáze životního cyklu aktivity má odpovídající metodu zpětného volání: onCreate(), onStart(), onPause() a tak dále. Když aktivita změní stav, je vyvolána přidružená metoda zpětného volání. Jednu z těchto metod jste již viděli: onCreate(). Přepsáním kterékoli z metod zpětného volání životního cyklu ve vašich třídách aktivity můžete změnit výchozí chování aktivity v reakci na akce uživatele nebo systému.

Stav aktivity se také může změnit v reakci na změny konfigurace zařízení, například když uživatel otočí zařízení z polohy na výšku do polohy na šířku. Když dojde k těmto změnám konfigurace, aktivita je zničena a znovu vytvořena ve výchozím stavu a uživatel může ztratit informace, které do aktivity zadal. Abyste své uživatele zmátli, je důležité, abyste svou aplikaci vyvinuli tak, aby se zabránilo neočekávané ztrátě dat. Později v tomto praktickém cvičení budete experimentovat se změnami konfigurace a naučíte se, jak zachovat stav aktivity v reakci na změny konfigurace zařízení a další události životního cyklu aktivity.

V tomto praktickém cvičení přidáte do aplikace TwoActivities příkazy protokolování a při používání aplikace pozorujete změny životního cyklu aktivit. Poté začnete pracovat s těmito změnami a prozkoumáte, jak za těchto podmínek zacházet s uživatelskými vstupy.

Předpoklady

Měli byste být schopni:

  • Vytvořte a spusťte projekt aplikace v Android Studiu .
  • Přidejte do aplikace příkazy protokolu a zobrazte tyto protokoly v podokně Logcat.
  • Porozumět aktivitě a záměru a pracovat s nimi a pracovat s nimi pohodlně.

Co se naučíte

  • Jak funguje životní cyklus aktivity.
  • Když se aktivita spustí, pozastaví, zastaví a zničí.
  • O metodách zpětného volání životního cyklu spojených se změnami aktivity.
  • Účinek akcí (jako jsou změny konfigurace), které mohou vést k událostem životního cyklu aktivity.
  • Jak zachovat stav aktivity napříč událostmi životního cyklu.

Co uděláš

  • Přidejte kód do aplikace TwoActivities z předchozího praktického cvičení, abyste mohli implementovat různá zpětná volání životního cyklu aktivity, aby zahrnovala příkazy protokolování.
  • Sledujte změny stavu při spuštění aplikace a při interakci s jednotlivými aktivitami v aplikaci.
  • Upravte svou aplikaci tak, aby zachovala stav instance aktivity, která je neočekávaně znovu vytvořena v reakci na chování uživatele nebo změnu konfigurace na zařízení.

2. Přehled aplikace

V tomto praktickém cvičení přidáte do aplikace TwoActivities . Aplikace vypadá a chová se zhruba stejně jako v poslední kódové laboratoři. Obsahuje dvě implementace aktivity a dává uživateli možnost posílat mezi nimi. Změny, které v aplikaci provedete v tomto praktickém cvičení, neovlivní její viditelné uživatelské chování.

3. 3. Úkol 1: Přidejte zpětná volání životního cyklu do TwoActivities

V této úloze implementujete všechny metody zpětného volání životního cyklu aktivity pro tisk zpráv do logcat, když jsou tyto metody vyvolány. Tyto zprávy protokolu vám umožní vidět, kdy se stav životního cyklu aktivity změní, a jak tyto změny stavu životního cyklu ovlivňují vaši aplikaci při jejím spuštění.

1.1 (Volitelné) Zkopírujte projekt TwoActivities

Pro úkoly v tomto praktickém cvičení upravíte stávající projekt TwoActivities , který jste vytvořili v posledním cvičení. Pokud si přejete ponechat předchozí projekt TwoActivities nedotčený, postupujte podle kroků v příloze: Nástroje a vytvořte kopii projektu.

1.2 Implementujte zpětná volání do MainActivity

  1. Otevřete projekt TwoActivities v Android Studiu a otevřete MainActivity v podokně Projekt > Android.
  2. V metodě onCreate() přidejte následující příkazy protokolu:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
  1. Přidejte přepsání zpětného volání onStart() s příkazem do protokolu pro tuto událost:
@Override
public void onStart(){
    super.onStart();
    Log.d(LOG_TAG, "onStart");
}

Jako zkratku vyberte Kód > Přepsat metody v Android Studio. Zobrazí se dialogové okno se všemi možnými metodami, které můžete ve své třídě přepsat. Výběrem jedné nebo více metod zpětného volání ze seznamu se vloží úplná šablona pro tyto metody, včetně požadovaného volání nadtřídy.

  1. Použijte metodu onStart() jako šablonu k implementaci zpětných volání životního cyklu onPause(), onRestart(), onResume(), onStop() a onDestroy().

Všechny metody zpětného volání mají stejné podpisy (kromě jména). Pokud pomocí funkce Copy and Paste onStart() vytvoříte tyto další metody zpětného volání, nezapomeňte aktualizovat obsah, aby volal správnou metodu v nadtřídě, a abyste zaprotokolovali správnou metodu.

  1. Spusťte aplikaci.
  2. Kliknutím na kartu Logcat v dolní části aplikace Android Studio zobrazíte podokno Logcat. Měli byste vidět tři zprávy protokolu zobrazující tři stavy životního cyklu, kterými aktivita prošla, když začala:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume

1.3 Implementujte zpětná volání životního cyklu v SecondActivity

Nyní, když jste implementovali metody zpětného volání životního cyklu pro MainActivity, udělejte totéž pro SecondActivity.

  1. Otevřete SecondActivity.
  2. Na začátek třídy přidejte konstantu pro proměnnou LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
  1. Přidejte zpětná volání životního cyklu a příkazy protokolu do druhé aktivity. (Metody zpětného volání můžete zkopírovat a vložit z MainActivity.)
  2. Přidejte příkaz protokolu do metody returnReply() těsně před metodu finish():
Log.d(LOG_TAG, "End SecondActivity");

1.4 Sledujte protokol během běhu aplikace**

  1. Spusťte aplikaci.
  2. Kliknutím na kartu Logcat v dolní části aplikace Android Studio zobrazíte podokno Logcat.
  3. Do vyhledávacího pole zadejte Aktivita. Android logcat může být velmi dlouhý a nepřehledný. Protože proměnná LOG_TAG v každé třídě obsahuje buď slova MainActivity nebo SecondActivity, toto klíčové slovo vám umožňuje filtrovat protokol pouze pro věci, které vás zajímají.

Dvojité potíže

Experimentujte s aplikací a všimněte si, že události životního cyklu, ke kterým dochází v reakci na různé akce. Vyzkoušejte zejména tyto věci:

  • Používejte aplikaci normálně (odešlete zprávu, odpovězte jinou zprávou).
  • Pomocí tlačítka Zpět se vrátíte z druhé aktivity do hlavní aktivity.
  • Pomocí šipky nahoru na liště aplikace se vrátíte z druhé aktivity do hlavní aktivity.
  • Otáčejte zařízením při hlavní i druhé aktivitě v různých časech v aplikaci a sledujte, co se děje v * protokolu a na obrazovce.
  • Stiskněte tlačítko přehledu (čtvercové tlačítko napravo od plochy) a zavřete aplikaci (klepněte na X).
  • Vraťte se na domovskou obrazovku a restartujte aplikaci.

TIP: Pokud aplikaci spouštíte v emulátoru, můžete rotaci simulovat pomocí Control+F11 nebo Control+Function+F11.

Kód řešení úkolu 1

Následující fragmenty kódu ukazují kód řešení pro první úlohu.

Hlavní Aktivita

Následující fragmenty kódu zobrazují přidaný kód v MainActivity, ale ne celou třídu.

Metoda onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Log the start of the onCreate() method.
        Log.d(LOG_TAG, "-------");
        Log.d(LOG_TAG, "onCreate");

        // Initialize all the view variables.
        mMessageEditText = findViewById(R.id.editText_main);
        mReplyHeadTextView = findViewById(R.id.text_header_reply);
        mReplyTextView = findViewById(R.id.text_message_reply);
}

Další metody životního cyklu:

@Override
protected void onStart() {
        super.onStart();
        Log.d(LOG_TAG, "onStart");
}

@Override
protected void onPause() {
        super.onPause();
        Log.d(LOG_TAG, "onPause");
}

@Override
protected void onRestart() {
        super.onRestart();
        Log.d(LOG_TAG, "onRestart");
}

@Override
protected void onResume() {
        super.onResume();
        Log.d(LOG_TAG, "onResume");
}

@Override
protected void onStop() {
        super.onStop();
        Log.d(LOG_TAG, "onStop");
}

@Override
protected void onDestroy() {
        super.onDestroy();
        Log.d(LOG_TAG, "onDestroy");
}

Druhá aktivita

Následující fragmenty kódu ukazují přidaný kód v SecondActivity, ale ne celou třídu.

Na vrcholu třídy SecondActivity:

private static final String LOG_TAG = SecondActivity.class.getSimpleName();

Metoda returnReply():

public void returnReply(View view) {
        String reply = mReply.getText().toString();
        Intent replyIntent = new Intent();
        replyIntent.putExtra(EXTRA_REPLY, reply);
        setResult(RESULT_OK, replyIntent);
        Log.d(LOG_TAG, "End SecondActivity");
        finish();
}

Další metody životního cyklu:

Stejné jako u MainActivity výše.

4. 4. Úloha 2: Uložte a obnovte stav instance aktivity

V závislosti na systémových prostředcích a chování uživatelů může být každá aktivita ve vaší aplikaci zničena a rekonstruována mnohem častěji, než si myslíte.

Možná jste si tohoto chování všimli v poslední části, když jste otočili zařízení nebo emulátor. Otočení zařízení je jedním z příkladů změny konfigurace zařízení. Ačkoli rotace je nejběžnější, všechny změny konfigurace mají za následek zničení aktuální aktivity a její opětovné vytvoření, jako by byla nová. Pokud toto chování ve svém kódu nezohledníte, může se při změně konfigurace vrátit vaše rozvržení aktivity do výchozího vzhledu a počátečních hodnot a vaši uživatelé mohou ztratit své místo, data nebo stav svého postupu v vaši aplikaci.

Stav každé aktivity je uložen jako sada párů klíč/hodnota v objektu Bundle, který se nazývá stav instance aktivity. Systém uloží výchozí informace o stavu do stavu instance Bundle těsně před zastavením aktivity a předá tento svazek nové instanci aktivity k obnovení.

Abyste zabránili ztrátě dat v Aktivitě, když jsou neočekávaně zničeny a znovu vytvořeny, musíte implementovat metodu onSaveInstanceState(). Systém volá tuto metodu u vaší aktivity (mezi onPause() a onStop()), když existuje možnost, že aktivita může být zničena a znovu vytvořena.

Data, která uložíte ve stavu instance, jsou specifická pouze pro tuto instanci této konkrétní aktivity během aktuální relace aplikace. Když zastavíte a restartujete novou relaci aplikace, stav instance aktivity se ztratí a aktivita se vrátí do výchozího vzhledu. Pokud potřebujete uložit uživatelská data mezi relacemi aplikace, použijte sdílené předvolby nebo databázi. O obou se dozvíte v pozdější praktické části.

2.1 Uložte stav instance aktivity pomocí onSaveInstanceState()

Možná jste si všimli, že otáčení zařízení vůbec neovlivňuje stav druhé aktivity. Je to proto, že druhé rozložení a stav aktivity jsou generovány z rozložení a záměru, který je aktivoval. I když je aktivita znovu vytvořena, záměr je stále k dispozici a data v tomto záměru se stále používají pokaždé, když je zavolána metoda onCreate() ve druhé aktivitě.

Kromě toho si můžete všimnout, že v každé Aktivitě je jakýkoli text, který jste zadali do prvků zprávy nebo odpovědi UpravitText, zachován, i když je zařízení otočeno. Je to proto, že informace o stavu některých prvků pohledu ve vašem rozvržení se automaticky ukládají při změnách konfigurace a aktuální hodnota EditText je jedním z těchto případů.

Takže jediný stav aktivity, který vás zajímá, jsou prvky TextView pro hlavičku odpovědi a text odpovědi v hlavní aktivitě. Oba prvky TextView jsou ve výchozím nastavení neviditelné; objeví se pouze poté, co odešlete zprávu zpět do hlavní aktivity z druhé aktivity.

V této úloze přidáte kód pro zachování stavu instance těchto dvou prvků TextView pomocí onSaveInstanceState().

  1. Otevřete MainActivity.
  2. Přidejte tuto implementaci kostry onSaveInstanceState() do aktivity nebo použijte Kód > Metody přepsání k vložení přepsání kostry.
@Override
public void onSaveInstanceState(Bundle outState) {
          super.onSaveInstanceState(outState);
}
  1. Zkontrolujte, zda je záhlaví aktuálně viditelné, a pokud ano, vložte stav viditelnosti do stavu Bundle pomocí metody putBoolean() a klíče "reply_visible".
 if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
        outState.putBoolean("reply_visible", true);
    }

Pamatujte, že záhlaví a text odpovědi jsou označeny jako neviditelné, dokud nepřijde odpověď z druhé aktivity. Pokud je hlavička viditelná, pak je potřeba uložit data odpovědi. Všimněte si, že nás zajímá pouze tento stav viditelnosti – skutečný text záhlaví není nutné ukládat, protože tento text se nikdy nemění.

  1. Uvnitř stejného zaškrtnutí přidejte text odpovědi do balíčku.
outState.putString("reply_text",mReplyTextView.getText().toString());

Pokud je záhlaví viditelné, můžete předpokládat, že je viditelná i samotná odpověď. Nemusíte testovat ani ukládat aktuální stav viditelnosti zprávy s odpovědí. Do stavu Bundle s klíčem "reply_text" přejde pouze vlastní text zprávy.

Uložíte stav pouze těch prvků pohledu, které se mohou po vytvoření aktivity změnit. Ostatní prvky zobrazení ve vaší aplikaci (Upravit text, tlačítko) lze kdykoli znovu vytvořit z výchozího rozvržení.

Všimněte si, že systém uloží stav některých prvků pohledu, jako je obsah EditText.

2.2 Obnovení stavu instance aktivity v onCreate()

Jakmile uložíte stav instance aktivity, musíte jej také obnovit při opětovném vytvoření aktivity. Můžete to udělat buď v onCreate(), nebo implementací zpětného volání onRestoreInstanceState(), které je voláno po onStart() po vytvoření aktivity.

Většinu času je lepší místo pro obnovení stavu aktivity v onCreate(), aby bylo zajištěno, že uživatelské rozhraní včetně stavu bude dostupné co nejdříve. Někdy je vhodné to udělat v onRestoreInstanceState() poté, co byla provedena veškerá inicializace, nebo umožnit podtřídám, aby se rozhodly, zda použít vaši výchozí implementaci.

  1. V metodě onCreate() po inicializaci proměnných View pomocí findViewById() přidejte test, abyste se ujistili, že saveInstanceState není null.
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);

// Restore the state.
if (savedInstanceState != null) {
}

Když je vaše aktivita vytvořena, systém předá stav Bundle onCreate() jako svůj jediný argument. Při prvním volání onCreate() a spuštění aplikace je balíček null – při prvním spuštění aplikace neexistuje žádný stav. Následná volání onCreate() mají balíček naplněný daty, která jste uložili v onSaveInstanceState().

  1. Uvnitř této kontroly získejte aktuální viditelnost (pravda nebo nepravda) z balíčku pomocí klíče "reply_visible".
if (savedInstanceState != null) {
    boolean isVisible = 
                     savedInstanceState.getBoolean("reply_visible");
}
  1. Pod předchozí řádek přidejte test pro proměnnou isVisible.
if (isVisible) {
}

Pokud je ve stavu Bundle klíč reply_visible (a isVisible je tedy pravdivý), budete muset stav obnovit.

  1. Uvnitř testu isVisible zviditelněte záhlaví.
mReplyHeadTextView.setVisibility(View.VISIBLE);
  1. Získejte textovou odpověď z balíčku pomocí klíče "reply_text" a nastavte textovou odpověď tak, aby zobrazovala tento řetězec.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
  1. Zviditelnit také odpověď TextView:
mReplyTextView.setVisibility(View.VISIBLE);
  1. Spusťte aplikaci. Zkuste otočit zařízením nebo emulátorem, abyste zajistili, že zpráva s odpovědí (pokud existuje) zůstane na obrazovce po opětovném vytvoření aktivity.

Kód řešení úkolu 2

Následující fragmenty kódu ukazují kód řešení pro tuto úlohu.

Hlavní Aktivita

Následující fragmenty kódu zobrazují přidaný kód v MainActivity, ale ne celou třídu.

Metoda onSaveInstanceState():

@Override
public void onSaveInstanceState(Bundle outState) {
   super.onSaveInstanceState(outState);
   // If the heading is visible, message needs to be saved.
   // Otherwise we're still using default layout.
   if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
       outState.putBoolean("reply_visible", true);
       outState.putString("reply_text", 
                      mReplyTextView.getText().toString());
   }
}

Metoda onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);

   Log.d(LOG_TAG, "-------");
   Log.d(LOG_TAG, "onCreate");

   // Initialize all the view variables.
   mMessageEditText = findViewById(R.id.editText_main);
   mReplyHeadTextView = findViewById(R.id.text_header_reply);
   mReplyTextView = findViewById(R.id.text_message_reply);

   // Restore the saved state. 
   // See onSaveInstanceState() for what gets saved.
   if (savedInstanceState != null) {
       boolean isVisible = 
                     savedInstanceState.getBoolean("reply_visible");
       // Show both the header and the message views. If isVisible is
       // false or missing from the bundle, use the default layout.
       if (isVisible) {
           mReplyHeadTextView.setVisibility(View.VISIBLE);
           mReplyTextView.setText(savedInstanceState
                                  .getString("reply_text"));
           mReplyTextView.setVisibility(View.VISIBLE);
       }
   }
}

Kompletní projekt:

Projekt Android Studio: TwoActivitiesLifecycle

5. Kódování

Úkol: Vytvořte jednoduchou aplikaci nákupního seznamu s hlavní aktivitou pro seznam, který uživatel vytváří, a druhou aktivitou pro seznam běžných nákupních položek.

  • Hlavní aktivita by měla obsahovat seznam k sestavení, který by měl tvořit deset prázdných prvků TextView.
  • Tlačítko Přidat položku v hlavní aktivitě spustí druhou aktivitu, která obsahuje seznam běžných nákupních položek (sýr, rýže, jablka atd.). K zobrazení položek použijte prvky tlačítka.
  • Výběr položky vrátí uživatele do hlavní aktivity a aktualizuje prázdný TextView tak, aby zahrnoval vybranou položku.

Použijte záměr k předání informací z jedné aktivity do druhé. Ujistěte se, že se aktuální stav nákupního seznamu uloží, když uživatel zařízení otočí.

6. Shrnutí

  • Životní cyklus aktivity je sada stavů, kterými aktivita migruje, počínaje okamžikem, kdy byla poprvé vytvořena, a konče, když systém Android získá zpět zdroje pro tuto aktivitu.
  • Jak uživatel přechází z jedné aktivity do druhé a uvnitř i mimo vaši aplikaci, každá aktivita se pohybuje mezi stavy životního cyklu aktivity.
  • Každý stav v životním cyklu aktivity má odpovídající metodu zpětného volání, kterou můžete přepsat ve své třídě aktivity.
  • Metody životního cyklu jsou onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
  • Přepsání metody zpětného volání životního cyklu vám umožní přidat chování, ke kterému dojde, když vaše aktivita přejde do tohoto stavu.
  • Metody přepisování kostry můžete do svých tříd v Android Studiu přidat pomocí Kód > Přepsat.
  • Změny konfigurace zařízení, jako je rotace, mají za následek zničení aktivity a její opětovné vytvoření, jako by byla nová.
  • Při změně konfigurace se zachová část stavu aktivity, včetně aktuálních hodnot prvků EditText. U všech ostatních dat musíte tato data výslovně uložit sami.
  • Uložit stav instance Activity v metodě onSaveInstanceState() .
  • Data o stavu instance jsou uložena jako jednoduché páry klíč/hodnota v balíčku. Pomocí metod Bundle můžete vložit data do balíčku a získat data zpět z balíčku.
  • Obnovte stav instance v onCreate(), což je preferovaný způsob, nebo onRestoreInstanceState(). Zadní
,

1. Vítejte

Tato praktická kódová laboratoř je součástí Unit 1: Začínáme v kurzu Android Developer Fundamentals (verze 2). Největší hodnotu z tohoto kurzu získáte, pokud budete postupně procházet kódovými laboratořemi:

  • Úplný seznam kódových laboratoří v kurzu najdete v článku Codelabs for Android Developer Fundamentals (V2).
  • Podrobnosti o kurzu, včetně odkazů na všechny koncepční kapitoly, aplikace a snímky, najdete v tématu Android Developer Fundamentals (verze 2).

Zavedení

V tomto praktickém cvičení se dozvíte více o životním cyklu aktivity. Životní cyklus je sada stavů, ve kterých může být aktivita během celé své životnosti, od okamžiku, kdy byla vytvořena, do doby, kdy je zničena a systém získává zpět své zdroje. Když uživatel přechází mezi aktivitami ve vaší aplikaci (a také do a z aplikace), aktivity přecházejí mezi různými stavy v jejich životních cyklech.

Dvojité potíže

Každá fáze životního cyklu aktivity má odpovídající metodu zpětného volání: onCreate(), onStart(), onPause() a tak dále. Když aktivita změní stav, je vyvolána přidružená metoda zpětného volání. Jednu z těchto metod jste již viděli: onCreate(). Přepsáním kterékoli z metod zpětného volání životního cyklu ve vašich třídách aktivity můžete změnit výchozí chování aktivity v reakci na akce uživatele nebo systému.

Stav aktivity se také může změnit v reakci na změny konfigurace zařízení, například když uživatel otočí zařízení z polohy na výšku do polohy na šířku. Když dojde k těmto změnám konfigurace, aktivita je zničena a znovu vytvořena ve výchozím stavu a uživatel může ztratit informace, které do aktivity zadal. Abyste své uživatele zmátli, je důležité, abyste svou aplikaci vyvinuli tak, aby se zabránilo neočekávané ztrátě dat. Později v tomto praktickém cvičení budete experimentovat se změnami konfigurace a naučíte se, jak zachovat stav aktivity v reakci na změny konfigurace zařízení a další události životního cyklu aktivity.

V tomto praktickém cvičení přidáte do aplikace TwoActivities příkazy protokolování a při používání aplikace pozorujete změny životního cyklu aktivit. Poté začnete pracovat s těmito změnami a prozkoumáte, jak za těchto podmínek zacházet s uživatelskými vstupy.

Předpoklady

Měli byste být schopni:

  • Vytvořte a spusťte projekt aplikace v Android Studiu .
  • Přidejte do aplikace příkazy protokolu a zobrazte tyto protokoly v podokně Logcat.
  • Porozumět aktivitě a záměru a pracovat s nimi a pracovat s nimi pohodlně.

Co se naučíte

  • Jak funguje životní cyklus aktivity.
  • Když se aktivita spustí, pozastaví, zastaví a zničí.
  • O metodách zpětného volání životního cyklu spojených se změnami aktivity.
  • Účinek akcí (jako jsou změny konfigurace), které mohou vést k událostem životního cyklu aktivity.
  • Jak zachovat stav aktivity napříč událostmi životního cyklu.

Co uděláš

  • Přidejte kód do aplikace TwoActivities z předchozího praktického cvičení, abyste mohli implementovat různá zpětná volání životního cyklu aktivity, aby zahrnovala příkazy protokolování.
  • Sledujte změny stavu při spuštění aplikace a při interakci s jednotlivými aktivitami v aplikaci.
  • Upravte svou aplikaci tak, aby zachovala stav instance aktivity, která je neočekávaně znovu vytvořena v reakci na chování uživatele nebo změnu konfigurace na zařízení.

2. Přehled aplikace

V tomto praktickém cvičení přidáte do aplikace TwoActivities . Aplikace vypadá a chová se zhruba stejně jako v poslední kódové laboratoři. Obsahuje dvě implementace aktivity a dává uživateli možnost posílat mezi nimi. Změny, které v aplikaci provedete v tomto praktickém cvičení, neovlivní její viditelné uživatelské chování.

3. 3. Úkol 1: Přidejte zpětná volání životního cyklu do TwoActivities

V této úloze implementujete všechny metody zpětného volání životního cyklu aktivity pro tisk zpráv do logcat, když jsou tyto metody vyvolány. Tyto zprávy protokolu vám umožní vidět, kdy se stav životního cyklu aktivity změní, a jak tyto změny stavu životního cyklu ovlivňují vaši aplikaci při jejím spuštění.

1.1 (Volitelné) Zkopírujte projekt TwoActivities

Pro úkoly v tomto praktickém cvičení upravíte stávající projekt TwoActivities , který jste vytvořili v posledním cvičení. Pokud si přejete ponechat předchozí projekt TwoActivities nedotčený, postupujte podle kroků v příloze: Nástroje a vytvořte kopii projektu.

1.2 Implementujte zpětná volání do MainActivity

  1. Otevřete projekt TwoActivities v Android Studiu a otevřete MainActivity v podokně Projekt > Android.
  2. V metodě onCreate() přidejte následující příkazy protokolu:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
  1. Přidejte přepsání zpětného volání onStart() s příkazem do protokolu pro tuto událost:
@Override
public void onStart(){
    super.onStart();
    Log.d(LOG_TAG, "onStart");
}

Jako zkratku vyberte Kód > Přepsat metody v Android Studio. Zobrazí se dialogové okno se všemi možnými metodami, které můžete ve své třídě přepsat. Výběrem jedné nebo více metod zpětného volání ze seznamu se vloží úplná šablona pro tyto metody, včetně požadovaného volání nadtřídy.

  1. Použijte metodu onStart() jako šablonu k implementaci zpětných volání životního cyklu onPause(), onRestart(), onResume(), onStop() a onDestroy().

Všechny metody zpětného volání mají stejné podpisy (kromě jména). Pokud pomocí funkce Copy and Paste onStart() vytvoříte tyto další metody zpětného volání, nezapomeňte aktualizovat obsah, aby volal správnou metodu v nadtřídě, a abyste zaprotokolovali správnou metodu.

  1. Spusťte aplikaci.
  2. Kliknutím na kartu Logcat v dolní části aplikace Android Studio zobrazíte podokno Logcat. Měli byste vidět tři zprávy protokolu zobrazující tři stavy životního cyklu, kterými aktivita prošla, když začala:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume

1.3 Implementujte zpětná volání životního cyklu v SecondActivity

Nyní, když jste implementovali metody zpětného volání životního cyklu pro MainActivity, udělejte totéž pro SecondActivity.

  1. Otevřete SecondActivity.
  2. Na začátek třídy přidejte konstantu pro proměnnou LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
  1. Přidejte zpětná volání životního cyklu a příkazy protokolu do druhé aktivity. (Metody zpětného volání můžete zkopírovat a vložit z MainActivity.)
  2. Přidejte příkaz protokolu do metody returnReply() těsně před metodu finish():
Log.d(LOG_TAG, "End SecondActivity");

1.4 Sledujte protokol během běhu aplikace**

  1. Spusťte aplikaci.
  2. Kliknutím na kartu Logcat v dolní části aplikace Android Studio zobrazíte podokno Logcat.
  3. Do vyhledávacího pole zadejte Aktivita. Android logcat může být velmi dlouhý a nepřehledný. Protože proměnná LOG_TAG v každé třídě obsahuje buď slova MainActivity nebo SecondActivity, toto klíčové slovo vám umožňuje filtrovat protokol pouze pro věci, které vás zajímají.

Dvojité potíže

Experimentujte s aplikací a všimněte si, že události životního cyklu, ke kterým dochází v reakci na různé akce. Vyzkoušejte zejména tyto věci:

  • Používejte aplikaci normálně (odešlete zprávu, odpovězte jinou zprávou).
  • Pomocí tlačítka Zpět se vrátíte z druhé aktivity do hlavní aktivity.
  • Pomocí šipky nahoru na liště aplikace se vrátíte z druhé aktivity do hlavní aktivity.
  • Otáčejte zařízením při hlavní i druhé aktivitě v různých časech v aplikaci a sledujte, co se děje v * protokolu a na obrazovce.
  • Stiskněte tlačítko přehledu (čtvercové tlačítko napravo od plochy) a zavřete aplikaci (klepněte na X).
  • Vraťte se na domovskou obrazovku a restartujte aplikaci.

TIP: Pokud aplikaci spouštíte v emulátoru, můžete rotaci simulovat pomocí Control+F11 nebo Control+Function+F11.

Kód řešení úkolu 1

Následující fragmenty kódu ukazují kód řešení pro první úlohu.

Hlavní Aktivita

Následující fragmenty kódu zobrazují přidaný kód v MainActivity, ale ne celou třídu.

Metoda onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Log the start of the onCreate() method.
        Log.d(LOG_TAG, "-------");
        Log.d(LOG_TAG, "onCreate");

        // Initialize all the view variables.
        mMessageEditText = findViewById(R.id.editText_main);
        mReplyHeadTextView = findViewById(R.id.text_header_reply);
        mReplyTextView = findViewById(R.id.text_message_reply);
}

Další metody životního cyklu:

@Override
protected void onStart() {
        super.onStart();
        Log.d(LOG_TAG, "onStart");
}

@Override
protected void onPause() {
        super.onPause();
        Log.d(LOG_TAG, "onPause");
}

@Override
protected void onRestart() {
        super.onRestart();
        Log.d(LOG_TAG, "onRestart");
}

@Override
protected void onResume() {
        super.onResume();
        Log.d(LOG_TAG, "onResume");
}

@Override
protected void onStop() {
        super.onStop();
        Log.d(LOG_TAG, "onStop");
}

@Override
protected void onDestroy() {
        super.onDestroy();
        Log.d(LOG_TAG, "onDestroy");
}

Druhá aktivita

Následující fragmenty kódu ukazují přidaný kód v SecondActivity, ale ne celou třídu.

Na vrcholu třídy SecondActivity:

private static final String LOG_TAG = SecondActivity.class.getSimpleName();

Metoda returnReply():

public void returnReply(View view) {
        String reply = mReply.getText().toString();
        Intent replyIntent = new Intent();
        replyIntent.putExtra(EXTRA_REPLY, reply);
        setResult(RESULT_OK, replyIntent);
        Log.d(LOG_TAG, "End SecondActivity");
        finish();
}

Další metody životního cyklu:

Stejné jako u MainActivity výše.

4. 4. Úloha 2: Uložte a obnovte stav instance aktivity

V závislosti na systémových prostředcích a chování uživatelů může být každá aktivita ve vaší aplikaci zničena a rekonstruována mnohem častěji, než si myslíte.

Možná jste si tohoto chování všimli v poslední části, když jste otočili zařízení nebo emulátor. Otočení zařízení je jedním z příkladů změny konfigurace zařízení. Ačkoli rotace je nejběžnější, všechny změny konfigurace mají za následek zničení aktuální aktivity a její opětovné vytvoření, jako by byla nová. Pokud toto chování ve svém kódu nezohledníte, může se při změně konfigurace vrátit vaše rozvržení aktivity do výchozího vzhledu a počátečních hodnot a vaši uživatelé mohou ztratit své místo, data nebo stav svého postupu v vaši aplikaci.

Stav každé aktivity je uložen jako sada párů klíč/hodnota v objektu Bundle, který se nazývá stav instance aktivity. Systém uloží výchozí informace o stavu do stavu instance Bundle těsně před zastavením aktivity a předá tento svazek nové instanci aktivity k obnovení.

Abyste zabránili ztrátě dat v Aktivitě, když jsou neočekávaně zničeny a znovu vytvořeny, musíte implementovat metodu onSaveInstanceState(). Systém volá tuto metodu u vaší aktivity (mezi onPause() a onStop()), když existuje možnost, že aktivita může být zničena a znovu vytvořena.

Data, která uložíte ve stavu instance, jsou specifická pouze pro tuto instanci této konkrétní aktivity během aktuální relace aplikace. Když zastavíte a restartujete novou relaci aplikace, stav instance aktivity se ztratí a aktivita se vrátí do výchozího vzhledu. Pokud potřebujete uložit uživatelská data mezi relacemi aplikace, použijte sdílené předvolby nebo databázi. O obou se dozvíte v pozdější praktické části.

2.1 Uložte stav instance aktivity pomocí onSaveInstanceState()

Možná jste si všimli, že otáčení zařízení vůbec neovlivňuje stav druhé aktivity. Je to proto, že druhé rozložení a stav aktivity jsou generovány z rozložení a záměru, který je aktivoval. I když je aktivita znovu vytvořena, záměr je stále k dispozici a data v tomto záměru se stále používají pokaždé, když je zavolána metoda onCreate() ve druhé aktivitě.

Kromě toho si můžete všimnout, že v každé Aktivitě je jakýkoli text, který jste zadali do prvků zprávy nebo odpovědi UpravitText, zachován, i když je zařízení otočeno. Je to proto, že informace o stavu některých prvků pohledu ve vašem rozvržení se automaticky ukládají při změnách konfigurace a aktuální hodnota EditText je jedním z těchto případů.

Takže jediný stav aktivity, který vás zajímá, jsou prvky TextView pro hlavičku odpovědi a text odpovědi v hlavní aktivitě. Oba prvky TextView jsou ve výchozím nastavení neviditelné; objeví se pouze poté, co odešlete zprávu zpět do hlavní aktivity z druhé aktivity.

V této úloze přidáte kód pro zachování stavu instance těchto dvou prvků TextView pomocí onSaveInstanceState().

  1. Otevřete MainActivity.
  2. Přidejte tuto implementaci kostry onSaveInstanceState() do aktivity nebo použijte Kód > Metody přepsání k vložení přepsání kostry.
@Override
public void onSaveInstanceState(Bundle outState) {
          super.onSaveInstanceState(outState);
}
  1. Zkontrolujte, zda je záhlaví aktuálně viditelné, a pokud ano, vložte stav viditelnosti do stavu Bundle pomocí metody putBoolean() a klíče "reply_visible".
 if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
        outState.putBoolean("reply_visible", true);
    }

Pamatujte, že záhlaví a text odpovědi jsou označeny jako neviditelné, dokud nepřijde odpověď z druhé aktivity. Pokud je hlavička viditelná, pak je potřeba uložit data odpovědi. Všimněte si, že nás zajímá pouze tento stav viditelnosti – skutečný text záhlaví není nutné ukládat, protože tento text se nikdy nemění.

  1. Uvnitř stejného zaškrtnutí přidejte text odpovědi do balíčku.
outState.putString("reply_text",mReplyTextView.getText().toString());

Pokud je záhlaví viditelné, můžete předpokládat, že je viditelná i samotná odpověď. Nemusíte testovat ani ukládat aktuální stav viditelnosti zprávy s odpovědí. Do stavu Bundle s klíčem "reply_text" přejde pouze vlastní text zprávy.

Uložíte stav pouze těch prvků pohledu, které se mohou po vytvoření aktivity změnit. Ostatní prvky zobrazení ve vaší aplikaci (Upravit text, tlačítko) lze kdykoli znovu vytvořit z výchozího rozvržení.

Všimněte si, že systém uloží stav některých prvků pohledu, jako je obsah EditText.

2.2 Obnovení stavu instance aktivity v onCreate()

Jakmile uložíte stav instance aktivity, musíte jej také obnovit při opětovném vytvoření aktivity. Můžete to udělat buď v onCreate(), nebo implementací zpětného volání onRestoreInstanceState(), které je voláno po onStart() po vytvoření aktivity.

Většinu času je lepší místo pro obnovení stavu aktivity v onCreate(), aby bylo zajištěno, že uživatelské rozhraní včetně stavu bude dostupné co nejdříve. Někdy je vhodné to udělat v onRestoreInstanceState() poté, co byla provedena veškerá inicializace, nebo umožnit podtřídám, aby se rozhodly, zda použít vaši výchozí implementaci.

  1. V metodě onCreate() po inicializaci proměnných View pomocí findViewById() přidejte test, abyste se ujistili, že saveInstanceState není null.
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);

// Restore the state.
if (savedInstanceState != null) {
}

Když je vaše aktivita vytvořena, systém předá stav Bundle onCreate() jako svůj jediný argument. Při prvním volání onCreate() a spuštění aplikace je balíček null – při prvním spuštění aplikace neexistuje žádný stav. Následná volání onCreate() mají balíček naplněný daty, která jste uložili v onSaveInstanceState().

  1. Uvnitř této kontroly získejte aktuální viditelnost (pravda nebo nepravda) z balíčku pomocí klíče "reply_visible".
if (savedInstanceState != null) {
    boolean isVisible = 
                     savedInstanceState.getBoolean("reply_visible");
}
  1. Pod předchozí řádek přidejte test pro proměnnou isVisible.
if (isVisible) {
}

Pokud je ve stavu Bundle klíč reply_visible (a isVisible je tedy pravdivý), budete muset stav obnovit.

  1. Uvnitř testu isVisible zviditelněte záhlaví.
mReplyHeadTextView.setVisibility(View.VISIBLE);
  1. Získejte textovou odpověď z balíčku pomocí klíče "reply_text" a nastavte textovou odpověď tak, aby zobrazovala tento řetězec.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
  1. Zviditelnit také odpověď TextView:
mReplyTextView.setVisibility(View.VISIBLE);
  1. Spusťte aplikaci. Zkuste otočit zařízením nebo emulátorem, abyste zajistili, že zpráva s odpovědí (pokud existuje) zůstane na obrazovce po opětovném vytvoření aktivity.

Kód řešení úkolu 2

Následující fragmenty kódu ukazují kód řešení pro tuto úlohu.

Hlavní Aktivita

Následující fragmenty kódu zobrazují přidaný kód v MainActivity, ale ne celou třídu.

Metoda onSaveInstanceState():

@Override
public void onSaveInstanceState(Bundle outState) {
   super.onSaveInstanceState(outState);
   // If the heading is visible, message needs to be saved.
   // Otherwise we're still using default layout.
   if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
       outState.putBoolean("reply_visible", true);
       outState.putString("reply_text", 
                      mReplyTextView.getText().toString());
   }
}

Metoda onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);

   Log.d(LOG_TAG, "-------");
   Log.d(LOG_TAG, "onCreate");

   // Initialize all the view variables.
   mMessageEditText = findViewById(R.id.editText_main);
   mReplyHeadTextView = findViewById(R.id.text_header_reply);
   mReplyTextView = findViewById(R.id.text_message_reply);

   // Restore the saved state. 
   // See onSaveInstanceState() for what gets saved.
   if (savedInstanceState != null) {
       boolean isVisible = 
                     savedInstanceState.getBoolean("reply_visible");
       // Show both the header and the message views. If isVisible is
       // false or missing from the bundle, use the default layout.
       if (isVisible) {
           mReplyHeadTextView.setVisibility(View.VISIBLE);
           mReplyTextView.setText(savedInstanceState
                                  .getString("reply_text"));
           mReplyTextView.setVisibility(View.VISIBLE);
       }
   }
}

Kompletní projekt:

Projekt Android Studio: TwoActivitiesLifecycle

5. Kódování

Úkol: Vytvořte jednoduchou aplikaci nákupního seznamu s hlavní aktivitou pro seznam, který uživatel vytváří, a druhou aktivitou pro seznam běžných nákupních položek.

  • Hlavní aktivita by měla obsahovat seznam k sestavení, který by měl tvořit deset prázdných prvků TextView.
  • Tlačítko Přidat položku v hlavní aktivitě spustí druhou aktivitu, která obsahuje seznam běžných nákupních položek (sýr, rýže, jablka atd.). K zobrazení položek použijte prvky tlačítka.
  • Výběr položky vrátí uživatele do hlavní aktivity a aktualizuje prázdný TextView tak, aby zahrnoval vybranou položku.

Použijte záměr k předání informací z jedné aktivity do druhé. Ujistěte se, že se aktuální stav nákupního seznamu uloží, když uživatel zařízení otočí.

6. Shrnutí

  • Životní cyklus aktivity je sada stavů, kterými aktivita migruje, počínaje okamžikem, kdy byla poprvé vytvořena, a konče, když systém Android získá zpět zdroje pro tuto aktivitu.
  • Jak uživatel přechází z jedné aktivity do druhé a uvnitř i mimo vaši aplikaci, každá aktivita se pohybuje mezi stavy životního cyklu aktivity.
  • Každý stav v životním cyklu aktivity má odpovídající metodu zpětného volání, kterou můžete přepsat ve své třídě aktivity.
  • Metody životního cyklu jsou onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
  • Přepsání metody zpětného volání životního cyklu vám umožní přidat chování, ke kterému dojde, když vaše aktivita přejde do tohoto stavu.
  • Metody přepisování kostry můžete do svých tříd v Android Studiu přidat pomocí Kód > Přepsat.
  • Změny konfigurace zařízení, jako je rotace, mají za následek zničení aktivity a její opětovné vytvoření, jako by byla nová.
  • Při změně konfigurace se zachová část stavu aktivity, včetně aktuálních hodnot prvků EditText. U všech ostatních dat musíte tato data výslovně uložit sami.
  • Uložit stav instance Activity v metodě onSaveInstanceState() .
  • Data o stavu instance jsou uložena jako jednoduché páry klíč/hodnota v balíčku. Pomocí metod Bundle můžete vložit data do balíčku a získat data zpět z balíčku.
  • Obnovte stav instance v onCreate(), což je preferovaný způsob, nebo onRestoreInstanceState(). Zadní
,

1. Vítejte

Tato praktická kódová laboratoř je součástí Unit 1: Začínáme v kurzu Android Developer Fundamentals (verze 2). Největší hodnotu z tohoto kurzu získáte, pokud budete postupně procházet kódovými laboratořemi:

  • Úplný seznam kódových laboratoří v kurzu najdete v článku Codelabs for Android Developer Fundamentals (V2).
  • Podrobnosti o kurzu, včetně odkazů na všechny koncepční kapitoly, aplikace a snímky, najdete v tématu Android Developer Fundamentals (verze 2).

Zavedení

V tomto praktickém cvičení se dozvíte více o životním cyklu aktivity. Životní cyklus je sada stavů, ve kterých může být aktivita během celé své životnosti, od okamžiku, kdy byla vytvořena, do doby, kdy je zničena a systém získává zpět své zdroje. Když uživatel přechází mezi aktivitami ve vaší aplikaci (a také do a z aplikace), aktivity přecházejí mezi různými stavy v jejich životních cyklech.

Dvojité potíže

Každá fáze životního cyklu aktivity má odpovídající metodu zpětného volání: onCreate(), onStart(), onPause() a tak dále. Když aktivita změní stav, je vyvolána přidružená metoda zpětného volání. Jednu z těchto metod jste již viděli: onCreate(). Přepsáním kterékoli z metod zpětného volání životního cyklu ve vašich třídách aktivity můžete změnit výchozí chování aktivity v reakci na akce uživatele nebo systému.

Stav aktivity se také může změnit v reakci na změny konfigurace zařízení, například když uživatel otočí zařízení z polohy na výšku do polohy na šířku. Když dojde k těmto změnám konfigurace, aktivita je zničena a znovu vytvořena ve výchozím stavu a uživatel může ztratit informace, které do aktivity zadal. Abyste své uživatele zmátli, je důležité, abyste svou aplikaci vyvinuli tak, aby se zabránilo neočekávané ztrátě dat. Později v tomto praktickém cvičení budete experimentovat se změnami konfigurace a naučíte se, jak zachovat stav aktivity v reakci na změny konfigurace zařízení a další události životního cyklu aktivity.

V tomto praktickém cvičení přidáte do aplikace TwoActivities příkazy protokolování a při používání aplikace pozorujete změny životního cyklu aktivit. Poté začnete pracovat s těmito změnami a prozkoumáte, jak za těchto podmínek zacházet s uživatelskými vstupy.

Předpoklady

Měli byste být schopni:

  • Vytvořte a spusťte projekt aplikace v Android Studiu .
  • Přidejte do aplikace příkazy protokolu a zobrazte tyto protokoly v podokně Logcat.
  • Porozumět aktivitě a záměru a pracovat s nimi a pracovat s nimi pohodlně.

Co se naučíte

  • Jak funguje životní cyklus aktivity.
  • Když se aktivita spustí, pozastaví, zastaví a zničí.
  • O metodách zpětného volání životního cyklu spojených se změnami aktivity.
  • Účinek akcí (jako jsou změny konfigurace), které mohou vést k událostem životního cyklu aktivity.
  • Jak zachovat stav aktivity napříč událostmi životního cyklu.

Co uděláš

  • Přidejte kód do aplikace TwoActivities z předchozího praktického cvičení, abyste mohli implementovat různá zpětná volání životního cyklu aktivity, aby zahrnovala příkazy protokolování.
  • Sledujte změny stavu při spuštění aplikace a při interakci s jednotlivými aktivitami v aplikaci.
  • Upravte svou aplikaci tak, aby zachovala stav instance aktivity, která je neočekávaně znovu vytvořena v reakci na chování uživatele nebo změnu konfigurace na zařízení.

2. Přehled aplikace

V tomto praktickém cvičení přidáte do aplikace TwoActivities . Aplikace vypadá a chová se zhruba stejně jako v poslední kódové laboratoři. Obsahuje dvě implementace aktivity a dává uživateli možnost posílat mezi nimi. Změny, které v aplikaci provedete v tomto praktickém cvičení, neovlivní její viditelné uživatelské chování.

3. 3. Úkol 1: Přidejte zpětná volání životního cyklu do TwoActivities

V této úloze implementujete všechny metody zpětného volání životního cyklu aktivity pro tisk zpráv do logcat, když jsou tyto metody vyvolány. Tyto zprávy protokolu vám umožní vidět, kdy se stav životního cyklu aktivity změní, a jak tyto změny stavu životního cyklu ovlivňují vaši aplikaci při jejím spuštění.

1.1 (Volitelné) Zkopírujte projekt TwoActivities

Pro úkoly v tomto praktickém cvičení upravíte stávající projekt TwoActivities , který jste vytvořili v posledním cvičení. Pokud si přejete ponechat předchozí projekt TwoActivities nedotčený, postupujte podle kroků v příloze: Nástroje a vytvořte kopii projektu.

1.2 Implementujte zpětná volání do MainActivity

  1. Otevřete projekt TwoActivities v Android Studiu a otevřete MainActivity v podokně Projekt > Android.
  2. V metodě onCreate() přidejte následující příkazy protokolu:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
  1. Přidejte přepsání zpětného volání onStart() s příkazem do protokolu pro tuto událost:
@Override
public void onStart(){
    super.onStart();
    Log.d(LOG_TAG, "onStart");
}

Jako zkratku vyberte Kód > Přepsat metody v Android Studio. Zobrazí se dialogové okno se všemi možnými metodami, které můžete ve své třídě přepsat. Výběrem jedné nebo více metod zpětného volání ze seznamu se vloží úplná šablona pro tyto metody, včetně požadovaného volání nadtřídy.

  1. Použijte metodu onStart() jako šablonu k implementaci zpětných volání životního cyklu onPause(), onRestart(), onResume(), onStop() a onDestroy().

Všechny metody zpětného volání mají stejné podpisy (kromě jména). Pokud pomocí funkce Copy and Paste onStart() vytvoříte tyto další metody zpětného volání, nezapomeňte aktualizovat obsah, aby volal správnou metodu v nadtřídě, a abyste zaprotokolovali správnou metodu.

  1. Spusťte aplikaci.
  2. Kliknutím na kartu Logcat v dolní části aplikace Android Studio zobrazíte podokno Logcat. Měli byste vidět tři zprávy protokolu zobrazující tři stavy životního cyklu, kterými aktivita prošla, když začala:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume

1.3 Implementujte zpětná volání životního cyklu v SecondActivity

Nyní, když jste implementovali metody zpětného volání životního cyklu pro MainActivity, udělejte totéž pro SecondActivity.

  1. Otevřete SecondActivity.
  2. Na začátek třídy přidejte konstantu pro proměnnou LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
  1. Přidejte zpětná volání životního cyklu a příkazy protokolu do druhé aktivity. (Metody zpětného volání můžete zkopírovat a vložit z MainActivity.)
  2. Přidejte příkaz protokolu do metody returnReply() těsně před metodu finish():
Log.d(LOG_TAG, "End SecondActivity");

1.4 Sledujte protokol během běhu aplikace**

  1. Spusťte aplikaci.
  2. Kliknutím na kartu Logcat v dolní části aplikace Android Studio zobrazíte podokno Logcat.
  3. Do vyhledávacího pole zadejte Aktivita. Android logcat může být velmi dlouhý a nepřehledný. Protože proměnná LOG_TAG v každé třídě obsahuje buď slova MainActivity nebo SecondActivity, toto klíčové slovo vám umožňuje filtrovat protokol pouze pro věci, které vás zajímají.

Dvojité potíže

Experimentujte s aplikací a všimněte si, že události životního cyklu, ke kterým dochází v reakci na různé akce. Vyzkoušejte zejména tyto věci:

  • Používejte aplikaci normálně (odešlete zprávu, odpovězte jinou zprávou).
  • Pomocí tlačítka Zpět se vrátíte z druhé aktivity do hlavní aktivity.
  • Pomocí šipky nahoru na liště aplikace se vrátíte z druhé aktivity do hlavní aktivity.
  • Otáčejte zařízením při hlavní i druhé aktivitě v různých časech v aplikaci a sledujte, co se děje v * protokolu a na obrazovce.
  • Stiskněte tlačítko přehledu (čtvercové tlačítko napravo od plochy) a zavřete aplikaci (klepněte na X).
  • Vraťte se na domovskou obrazovku a restartujte aplikaci.

TIP: Pokud aplikaci spouštíte v emulátoru, můžete rotaci simulovat pomocí Control+F11 nebo Control+Function+F11.

Kód řešení úkolu 1

Následující fragmenty kódu ukazují kód řešení pro první úlohu.

Hlavní Aktivita

Následující fragmenty kódu zobrazují přidaný kód v MainActivity, ale ne celou třídu.

Metoda onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Log the start of the onCreate() method.
        Log.d(LOG_TAG, "-------");
        Log.d(LOG_TAG, "onCreate");

        // Initialize all the view variables.
        mMessageEditText = findViewById(R.id.editText_main);
        mReplyHeadTextView = findViewById(R.id.text_header_reply);
        mReplyTextView = findViewById(R.id.text_message_reply);
}

Další metody životního cyklu:

@Override
protected void onStart() {
        super.onStart();
        Log.d(LOG_TAG, "onStart");
}

@Override
protected void onPause() {
        super.onPause();
        Log.d(LOG_TAG, "onPause");
}

@Override
protected void onRestart() {
        super.onRestart();
        Log.d(LOG_TAG, "onRestart");
}

@Override
protected void onResume() {
        super.onResume();
        Log.d(LOG_TAG, "onResume");
}

@Override
protected void onStop() {
        super.onStop();
        Log.d(LOG_TAG, "onStop");
}

@Override
protected void onDestroy() {
        super.onDestroy();
        Log.d(LOG_TAG, "onDestroy");
}

Druhá aktivita

Následující fragmenty kódu ukazují přidaný kód v SecondActivity, ale ne celou třídu.

Na vrcholu třídy SecondActivity:

private static final String LOG_TAG = SecondActivity.class.getSimpleName();

Metoda returnReply():

public void returnReply(View view) {
        String reply = mReply.getText().toString();
        Intent replyIntent = new Intent();
        replyIntent.putExtra(EXTRA_REPLY, reply);
        setResult(RESULT_OK, replyIntent);
        Log.d(LOG_TAG, "End SecondActivity");
        finish();
}

Další metody životního cyklu:

Stejné jako u MainActivity výše.

4. 4. Úloha 2: Uložte a obnovte stav instance aktivity

V závislosti na systémových prostředcích a chování uživatelů může být každá aktivita ve vaší aplikaci zničena a rekonstruována mnohem častěji, než si myslíte.

Možná jste si tohoto chování všimli v poslední části, když jste otočili zařízení nebo emulátor. Otočení zařízení je jedním z příkladů změny konfigurace zařízení. Ačkoli rotace je nejběžnější, všechny změny konfigurace mají za následek zničení aktuální aktivity a její opětovné vytvoření, jako by byla nová. Pokud toto chování ve svém kódu nezohledníte, může se při změně konfigurace vrátit vaše rozvržení aktivity do výchozího vzhledu a počátečních hodnot a vaši uživatelé mohou ztratit své místo, data nebo stav svého postupu v vaši aplikaci.

Stav každé aktivity je uložen jako sada párů klíč/hodnota v objektu Bundle, který se nazývá stav instance aktivity. Systém uloží výchozí informace o stavu do stavu instance Bundle těsně před zastavením aktivity a předá tento svazek nové instanci aktivity k obnovení.

Abyste zabránili ztrátě dat v Aktivitě, když jsou neočekávaně zničeny a znovu vytvořeny, musíte implementovat metodu onSaveInstanceState(). Systém volá tuto metodu u vaší aktivity (mezi onPause() a onStop()), když existuje možnost, že aktivita může být zničena a znovu vytvořena.

Data, která uložíte ve stavu instance, jsou specifická pouze pro tuto instanci této konkrétní aktivity během aktuální relace aplikace. Když zastavíte a restartujete novou relaci aplikace, stav instance aktivity se ztratí a aktivita se vrátí do výchozího vzhledu. Pokud potřebujete uložit uživatelská data mezi relacemi aplikace, použijte sdílené předvolby nebo databázi. O obou se dozvíte v pozdější praktické části.

2.1 Uložte stav instance aktivity pomocí onSaveInstanceState()

Možná jste si všimli, že otáčení zařízení vůbec neovlivňuje stav druhé aktivity. Je to proto, že druhé rozložení a stav aktivity jsou generovány z rozložení a záměru, který je aktivoval. I když je aktivita znovu vytvořena, záměr je stále k dispozici a data v tomto záměru se stále používají pokaždé, když je zavolána metoda onCreate() ve druhé aktivitě.

Kromě toho si můžete všimnout, že v každé Aktivitě je jakýkoli text, který jste zadali do prvků zprávy nebo odpovědi UpravitText, zachován, i když je zařízení otočeno. Je to proto, že informace o stavu některých prvků pohledu ve vašem rozvržení se automaticky ukládají při změnách konfigurace a aktuální hodnota EditText je jedním z těchto případů.

Takže jediný stav aktivity, který vás zajímá, jsou prvky TextView pro hlavičku odpovědi a text odpovědi v hlavní aktivitě. Oba prvky TextView jsou ve výchozím nastavení neviditelné; objeví se pouze poté, co odešlete zprávu zpět do hlavní aktivity z druhé aktivity.

V této úloze přidáte kód pro zachování stavu instance těchto dvou prvků TextView pomocí onSaveInstanceState().

  1. Otevřete MainActivity.
  2. Přidejte tuto implementaci kostry onSaveInstanceState() do aktivity nebo použijte Kód > Metody přepsání k vložení přepsání kostry.
@Override
public void onSaveInstanceState(Bundle outState) {
          super.onSaveInstanceState(outState);
}
  1. Zkontrolujte, zda je záhlaví aktuálně viditelné, a pokud ano, vložte stav viditelnosti do stavu Bundle pomocí metody putBoolean() a klíče "reply_visible".
 if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
        outState.putBoolean("reply_visible", true);
    }

Pamatujte, že záhlaví a text odpovědi jsou označeny jako neviditelné, dokud nepřijde odpověď z druhé aktivity. Pokud je hlavička viditelná, pak je potřeba uložit data odpovědi. Všimněte si, že nás zajímá pouze tento stav viditelnosti – skutečný text záhlaví není nutné ukládat, protože tento text se nikdy nemění.

  1. Uvnitř stejného zaškrtnutí přidejte text odpovědi do balíčku.
outState.putString("reply_text",mReplyTextView.getText().toString());

Pokud je záhlaví viditelné, můžete předpokládat, že je viditelná i samotná odpověď. Nemusíte testovat ani ukládat aktuální stav viditelnosti zprávy s odpovědí. Do stavu Bundle s klíčem "reply_text" přejde pouze vlastní text zprávy.

Uložíte stav pouze těch prvků pohledu, které se mohou po vytvoření aktivity změnit. Ostatní prvky zobrazení ve vaší aplikaci (Upravit text, tlačítko) lze kdykoli znovu vytvořit z výchozího rozvržení.

Všimněte si, že systém uloží stav některých prvků pohledu, jako je obsah EditText.

2.2 Obnovení stavu instance aktivity v onCreate()

Jakmile uložíte stav instance aktivity, musíte jej také obnovit při opětovném vytvoření aktivity. Můžete to udělat buď v onCreate(), nebo implementací zpětného volání onRestoreInstanceState(), které je voláno po onStart() po vytvoření aktivity.

Většinu času je lepší místo pro obnovení stavu aktivity v onCreate(), aby bylo zajištěno, že uživatelské rozhraní včetně stavu bude dostupné co nejdříve. Někdy je vhodné to udělat v onRestoreInstanceState() poté, co byla provedena veškerá inicializace, nebo umožnit podtřídám, aby se rozhodly, zda použít vaši výchozí implementaci.

  1. V metodě onCreate() po inicializaci proměnných View pomocí findViewById() přidejte test, abyste se ujistili, že saveInstanceState není null.
// Initialize all the view variables.
mMessageEditText = findViewById(R.id.editText_main);
mReplyHeadTextView = findViewById(R.id.text_header_reply);
mReplyTextView = findViewById(R.id.text_message_reply);

// Restore the state.
if (savedInstanceState != null) {
}

Když je vaše aktivita vytvořena, systém předá stav Bundle onCreate() jako svůj jediný argument. Při prvním volání onCreate() a spuštění aplikace je balíček null – při prvním spuštění aplikace neexistuje žádný stav. Následná volání onCreate() mají balíček naplněný daty, která jste uložili v onSaveInstanceState().

  1. Uvnitř této kontroly získejte aktuální viditelnost (pravda nebo nepravda) z balíčku pomocí klíče "reply_visible".
if (savedInstanceState != null) {
    boolean isVisible = 
                     savedInstanceState.getBoolean("reply_visible");
}
  1. Pod předchozí řádek přidejte test pro proměnnou isVisible.
if (isVisible) {
}

Pokud je ve stavu Bundle klíč reply_visible (a isVisible je tedy pravdivý), budete muset stav obnovit.

  1. Uvnitř testu isVisible zviditelněte záhlaví.
mReplyHeadTextView.setVisibility(View.VISIBLE);
  1. Získejte textovou odpověď z balíčku pomocí klíče "reply_text" a nastavte textovou odpověď tak, aby zobrazovala tento řetězec.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
  1. Zviditelnit také odpověď TextView:
mReplyTextView.setVisibility(View.VISIBLE);
  1. Spusťte aplikaci. Zkuste otočit zařízením nebo emulátorem, abyste zajistili, že zpráva s odpovědí (pokud existuje) zůstane na obrazovce po opětovném vytvoření aktivity.

Kód řešení úkolu 2

Následující fragmenty kódu ukazují kód řešení pro tuto úlohu.

Hlavní Aktivita

Následující fragmenty kódu zobrazují přidaný kód v MainActivity, ale ne celou třídu.

Metoda onSaveInstanceState():

@Override
public void onSaveInstanceState(Bundle outState) {
   super.onSaveInstanceState(outState);
   // If the heading is visible, message needs to be saved.
   // Otherwise we're still using default layout.
   if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
       outState.putBoolean("reply_visible", true);
       outState.putString("reply_text", 
                      mReplyTextView.getText().toString());
   }
}

Metoda onCreate():

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);

   Log.d(LOG_TAG, "-------");
   Log.d(LOG_TAG, "onCreate");

   // Initialize all the view variables.
   mMessageEditText = findViewById(R.id.editText_main);
   mReplyHeadTextView = findViewById(R.id.text_header_reply);
   mReplyTextView = findViewById(R.id.text_message_reply);

   // Restore the saved state. 
   // See onSaveInstanceState() for what gets saved.
   if (savedInstanceState != null) {
       boolean isVisible = 
                     savedInstanceState.getBoolean("reply_visible");
       // Show both the header and the message views. If isVisible is
       // false or missing from the bundle, use the default layout.
       if (isVisible) {
           mReplyHeadTextView.setVisibility(View.VISIBLE);
           mReplyTextView.setText(savedInstanceState
                                  .getString("reply_text"));
           mReplyTextView.setVisibility(View.VISIBLE);
       }
   }
}

Kompletní projekt:

Projekt Android Studio: TwoActivitiesLifecycle

5. Kódování

Úkol: Vytvořte jednoduchou aplikaci nákupního seznamu s hlavní aktivitou pro seznam, který uživatel vytváří, a druhou aktivitou pro seznam běžných nákupních položek.

  • Hlavní aktivita by měla obsahovat seznam k sestavení, který by měl tvořit deset prázdných prvků TextView.
  • Tlačítko Přidat položku v hlavní aktivitě spustí druhou aktivitu, která obsahuje seznam běžných nákupních položek (sýr, rýže, jablka atd.). K zobrazení položek použijte prvky tlačítka.
  • Výběr položky vrátí uživatele do hlavní aktivity a aktualizuje prázdný TextView tak, aby zahrnoval vybranou položku.

Použijte záměr k předání informací z jedné aktivity do druhé. Ujistěte se, že se aktuální stav nákupního seznamu uloží, když uživatel zařízení otočí.

6. Shrnutí

  • Životní cyklus aktivity je sada stavů, kterými aktivita migruje, počínaje okamžikem, kdy byla poprvé vytvořena, a konče, když systém Android získá zpět zdroje pro tuto aktivitu.
  • Jak uživatel přechází z jedné aktivity do druhé a uvnitř i mimo vaši aplikaci, každá aktivita se pohybuje mezi stavy životního cyklu aktivity.
  • Každý stav v životním cyklu aktivity má odpovídající metodu zpětného volání, kterou můžete přepsat ve své třídě aktivity.
  • Metody životního cyklu jsou onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
  • Přepsání metody zpětného volání životního cyklu vám umožní přidat chování, ke kterému dojde, když vaše aktivita přejde do tohoto stavu.
  • Metody přepisování kostry můžete do svých tříd v Android Studiu přidat pomocí Kód > Přepsat.
  • Změny konfigurace zařízení, jako je rotace, mají za následek zničení aktivity a její opětovné vytvoření, jako by byla nová.
  • Při změně konfigurace se zachová část stavu aktivity, včetně aktuálních hodnot prvků EditText. U všech ostatních dat musíte tato data výslovně uložit sami.
  • Uložit stav instance Activity v metodě onSaveInstanceState() .
  • Data o stavu instance jsou uložena jako jednoduché páry klíč/hodnota v balíčku. Pomocí metod Bundle můžete vložit data do balíčku a získat data zpět z balíčku.
  • Obnovte stav instance v onCreate(), což je preferovaný způsob, nebo onRestoreInstanceState(). Zadní