Ako používať životný cyklus a stav aktivity,Ako používať životný cyklus a stav aktivity

1. Vitajte

Toto praktické kódové laboratórium je súčasťou jednotky 1: Začíname v kurze Android Developer Fundamentals (verzia 2). Najväčšiu hodnotu z tohto kurzu získate, ak budete postupne prechádzať kódovými laboratóriami:

  • Úplný zoznam kódových laboratórií v kurze nájdete v téme Codelabs for Android Developer Fundamentals (V2).
  • Podrobnosti o kurze vrátane odkazov na všetky koncepčné kapitoly, aplikácie a snímky nájdete v téme Základy vývojárov pre Android (verzia 2).

Úvod

V tomto praktickom cvičení sa dozviete viac o životnom cykle aktivity. Životný cyklus je množina stavov, v ktorých môže byť aktivita počas celej svojej životnosti, od jej vytvorenia až po jej zničenie a opätovné získanie zdrojov. Keď používateľ prechádza medzi aktivitami vo vašej aplikácii (ako aj do a z aplikácie), aktivity prechádzajú medzi rôznymi stavmi vo svojich životných cykloch.

Dvojité problémy

Každá fáza životného cyklu aktivity má zodpovedajúcu metódu spätného volania: onCreate(), onStart(), onPause() atď. Keď aktivita zmení stav, vyvolá sa súvisiaca metóda spätného volania. Už ste videli jednu z týchto metód: onCreate(). Prepísaním ktorejkoľvek z metód spätného volania životného cyklu vo vašich triedach aktivity môžete zmeniť predvolené správanie aktivity v reakcii na akcie používateľa alebo systému.

Stav aktivity sa môže zmeniť aj v reakcii na zmeny konfigurácie zariadenia, napríklad keď používateľ otočí zariadenie z polohy na výšku na šírku. Keď dôjde k týmto zmenám konfigurácie, aktivita sa zničí a znovu vytvorí v predvolenom stave a používateľ môže stratiť informácie, ktoré do aktivity zadal. Aby ste predišli zmätku používateľov, je dôležité, aby ste svoju aplikáciu vyvinuli, aby ste predišli neočakávanej strate údajov. Neskôr v tomto praktickom cvičení budete experimentovať so zmenami konfigurácie a naučíte sa, ako zachovať stav aktivity v reakcii na zmeny konfigurácie zariadenia a iné udalosti životného cyklu aktivity.

V tomto praktickom cvičení pridáte do aplikácie TwoActivities výpisy protokolov a počas používania aplikácie budete sledovať zmeny životného cyklu aktivity. Potom začnete pracovať s týmito zmenami a skúmať, ako za týchto podmienok zaobchádzať so vstupom používateľa.

Predpoklady

Mali by ste byť schopní:

  • Vytvorte a spustite projekt aplikácie v aplikácii Android Studio .
  • Pridajte výpisy denníka do svojej aplikácie a zobrazte tieto denníky na table Logcat.
  • Pochopte aktivitu a zámer a pracujte s nimi a bavte sa s nimi pohodlne.

Čo sa naučíte

  • Ako funguje životný cyklus aktivity.
  • Keď sa aktivita spustí, pozastaví, zastaví a zničí.
  • O metódach spätného volania počas životného cyklu spojených so zmenami aktivity.
  • Účinok akcií (ako sú zmeny konfigurácie), ktoré môžu viesť k udalostiam životného cyklu aktivity.
  • Ako zachovať stav aktivity počas udalostí životného cyklu.

Čo urobíš

  • Pridajte kód do aplikácie TwoActivities z predchádzajúcej praktickej časti, aby ste implementovali rôzne spätné volania životného cyklu aktivity, aby zahŕňali protokoly.
  • Sledujte zmeny stavu pri spustení vašej aplikácie a pri interakcii s každou aktivitou vo vašej aplikácii.
  • Upravte svoju aplikáciu tak, aby si zachovala stav inštancie aktivity, ktorá sa neočakávane znova vytvorí v reakcii na správanie používateľa alebo zmenu konfigurácie na zariadení.

2. Prehľad aplikácie

V tejto praktickej časti pridáte do aplikácie TwoActivities . Aplikácia vyzerá a správa sa približne rovnako ako v poslednom kódovom laboratóriu. Obsahuje dve implementácie aktivity a dáva používateľovi možnosť posielať medzi nimi. Zmeny, ktoré v aplikácii vykonáte v tejto praktickej časti, neovplyvnia jej viditeľné používateľské správanie.

3. 3. Úloha 1: Pridajte spätné volania počas životného cyklu do TwoActivities

V tejto úlohe implementujete všetky metódy spätného volania životného cyklu aktivity na tlač správ do logcat, keď sú tieto metódy vyvolané. Tieto správy denníka vám umožnia zistiť, kedy sa zmení stav životného cyklu aktivity a ako tieto zmeny stavu životného cyklu ovplyvňujú vašu aplikáciu počas jej spustenia.

1.1 (Voliteľné) Skopírujte projekt TwoActivities

Pre úlohy v tomto cvičení upravíte existujúci projekt TwoActivities , ktorý ste vytvorili v poslednom cvičení. Ak chcete zachovať predchádzajúci projekt TwoActivities nedotknutý, postupujte podľa krokov v časti Príloha: Pomôcky a vytvorte kópiu projektu.

1.2 Implementujte spätné volania do MainActivity

  1. Otvorte projekt TwoActivities v Android Studio a otvorte MainActivity na table Project > Android.
  2. V metóde onCreate() pridajte nasledujúce príkazy protokolu:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
  1. Pridajte prepísanie pre spätné volanie onStart() s príkazom do protokolu pre túto udalosť:
@Override
public void onStart(){
    super.onStart();
    Log.d(LOG_TAG, "onStart");
}

Pre skratku vyberte Kód > Prepísať metódy v Android Studio. Zobrazí sa dialógové okno so všetkými možnými metódami, ktoré môžete vo svojej triede prepísať. Výberom jednej alebo viacerých metód spätného volania zo zoznamu sa vloží úplná šablóna pre tieto metódy vrátane požadovaného volania nadtriedy.

  1. Použite metódu onStart() ako šablónu na implementáciu spätných volaní životného cyklu onPause(), onRestart(), onResume(), onStop() a onDestroy()

Všetky metódy spätného volania majú rovnaké podpisy (okrem mena). Ak vytvoríte tieto ďalšie metódy spätného volania Copy and Paste onStart(), nezabudnite aktualizovať obsah, aby ste zavolali správnu metódu v nadtriede a zapísali správnu metódu.

  1. Spustite svoju aplikáciu.
  2. Kliknutím na kartu Logcat v spodnej časti aplikácie Android Studio zobrazíte tablu Logcat. Mali by ste vidieť tri správy denníka zobrazujúce tri stavy životného cyklu, cez ktoré aktivita prešla, keď začala:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume

1.3 Implementujte spätné volania počas životného cyklu v SecondActivity

Teraz, keď ste implementovali metódy spätného volania životného cyklu pre MainActivity, urobte to isté pre SecondActivity.

  1. Otvorte SecondActivity.
  2. V hornej časti triedy pridajte konštantu pre premennú LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
  1. Pridajte spätné volania a protokoly životného cyklu do druhej aktivity. (Môžete skopírovať a prilepiť metódy spätného volania z MainActivity.)
  2. Pridajte príkaz protokolu do metódy returnReply() tesne pred metódou finish():
Log.d(LOG_TAG, "End SecondActivity");

1.4 Sledujte denník pri spustení aplikácie**

  1. Spustite svoju aplikáciu.
  2. Kliknutím na kartu Logcat v spodnej časti aplikácie Android Studio zobrazíte tablu Logcat.
  3. Do vyhľadávacieho poľa zadajte Aktivita. Android logcat môže byť veľmi dlhý a neprehľadný. Pretože premenná LOG_TAG v každej triede obsahuje buď slová MainActivity alebo SecondActivity, toto kľúčové slovo vám umožňuje filtrovať protokol len pre veci, ktoré vás zaujímajú.

Dvojité problémy

Experimentujte s aplikáciou a všimnite si, že udalosti životného cyklu, ktoré sa vyskytujú v reakcii na rôzne akcie. Skúste najmä tieto veci:

  • Aplikáciu používajte normálne (odošlite správu, odpovedzte inou správou).
  • Pomocou tlačidla Späť sa vrátite z druhej aktivity do hlavnej aktivity.
  • Pomocou šípky nahor na paneli aplikácií sa vrátite z druhej aktivity do hlavnej aktivity.
  • Otáčajte zariadením pri hlavnej aj druhej aktivite v rôznych časoch v aplikácii a sledujte, čo sa deje v * protokole a na obrazovke.
  • Stlačte tlačidlo prehľadu (štvorcové tlačidlo napravo od plochy) a zatvorte aplikáciu (klepnite na X).
  • Vráťte sa na domovskú obrazovku a reštartujte aplikáciu.

TIP: Ak máte aplikáciu spustenú v emulátore, môžete simulovať rotáciu pomocou Ctrl+F11 alebo Ctrl+Function+F11.

Kód riešenia úlohy 1

Nasledujúce útržky kódu zobrazujú kód riešenia pre prvú úlohu.

Hlavná aktivita

Nasledujúce úryvky kódu zobrazujú pridaný kód v MainActivity, ale nie celú triedu.

Metóda 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);
}

Ďalšie metódy ž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

Nasledujúce úryvky kódu zobrazujú pridaný kód v SecondActivity, ale nie celú triedu.

Na vrchole triedy SecondActivity:

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

Metóda 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();
}

Ďalšie metódy životného cyklu:

Rovnako ako v prípade MainActivity vyššie.

4. 4. Úloha 2: Uložte a obnovte stav inštancie aktivity

V závislosti od systémových prostriedkov a správania používateľov môže byť každá aktivita vo vašej aplikácii zničená a rekonštruovaná oveľa častejšie, než by ste si mysleli.

Toto správanie ste si mohli všimnúť v poslednej časti, keď ste otáčali zariadením alebo emulátorom. Otáčanie zariadenia je jedným z príkladov zmeny konfigurácie zariadenia. Hoci rotácia je najbežnejšia, všetky zmeny konfigurácie vedú k zničeniu aktuálnej aktivity a jej opätovnému vytvoreniu, ako keby bola nová. Ak toto správanie nezohľadníte vo svojom kóde, keď dôjde ku zmene konfigurácie, vaše rozloženie aktivity sa môže vrátiť na svoj predvolený vzhľad a počiatočné hodnoty a vaši používatelia môžu stratiť svoje miesto, svoje údaje alebo stav svojho postupu v vašu aplikáciu.

Stav každej aktivity je uložený ako množina párov kľúč/hodnota v objekte Bundle, ktorý sa nazýva stav inštancie aktivity. Systém uloží informácie o predvolenom stave do stavu inštancie Bundle tesne pred zastavením aktivity a odovzdá tento balík do novej inštancie aktivity na obnovenie.

Ak chcete zabrániť strate údajov v aktivite, keď sú neočakávane zničené a znovu vytvorené, musíte implementovať metódu onSaveInstanceState(). Systém volá túto metódu pri vašej aktivite (medzi onPause() a onStop()), keď existuje možnosť, že aktivita môže byť zničená a znovu vytvorená.

Údaje, ktoré uložíte v stave inštancie, sú špecifické iba pre túto inštanciu tejto konkrétnej aktivity počas aktuálnej relácie aplikácie. Keď zastavíte a reštartujete novú reláciu aplikácie, stav inštancie aktivity sa stratí a aktivita sa vráti do predvoleného vzhľadu. Ak potrebujete uložiť používateľské údaje medzi reláciami aplikácie, použite zdieľané predvoľby alebo databázu. O oboch sa dozviete v neskoršom praktickom cvičení.

2.1 Uložte stav inštancie aktivity pomocou onSaveInstanceState()

Možno ste si všimli, že otáčanie zariadenia vôbec neovplyvňuje stav druhej aktivity. Je to preto, že druhé rozloženie a stav aktivity sú generované z rozloženia a zámeru, ktorý ho aktivoval. Aj keď je aktivita znovu vytvorená, zámer je stále prítomný a údaje v tomto zámere sa stále používajú pri každom volaní metódy onCreate() v druhej aktivite.

Okrem toho si môžete všimnúť, že pri každej aktivite sa akýkoľvek text, ktorý ste zadali do správy alebo do prvkov odpovede Upraviť text, zachová aj pri otočení zariadenia. Je to preto, že informácie o stave niektorých prvkov zobrazenia vo vašom rozložení sa automaticky ukladajú pri zmenách konfigurácie a aktuálna hodnota EditText je jedným z týchto prípadov.

Takže jediný stav aktivity, ktorý vás zaujíma, sú prvky TextView pre hlavičku odpovede a text odpovede v hlavnej aktivite. Oba prvky TextView sú štandardne neviditeľné; objavia sa až po odoslaní správy z druhej aktivity späť do hlavnej aktivity.

V tejto úlohe pridáte kód na zachovanie stavu inštancie týchto dvoch prvkov TextView pomocou onSaveInstanceState().

  1. Otvorte MainActivity.
  2. Pridajte túto implementáciu kostry onSaveInstanceState() do aktivity alebo použite Kód > Metódy prepísania na vloženie prepísania kostry.
@Override
public void onSaveInstanceState(Bundle outState) {
          super.onSaveInstanceState(outState);
}
  1. Skontrolujte, či je hlavička aktuálne viditeľná, a ak áno, vložte stav viditeľnosti do stavu Bundle pomocou metódy putBoolean() a kľúča "reply_visible".
 if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
        outState.putBoolean("reply_visible", true);
    }

Nezabudnite, že hlavička odpovede a text sú označené ako neviditeľné, kým nepríde odpoveď z druhej aktivity. Ak je hlavička viditeľná, potom je potrebné uložiť údaje odpovede. Všimnite si, že nás zaujíma iba tento stav viditeľnosti – skutočný text hlavičky nie je potrebné ukladať, pretože tento text sa nikdy nemení.

  1. V rámci toho istého zaškrtnutia pridajte text odpovede do balíka.
outState.putString("reply_text",mReplyTextView.getText().toString());

Ak je hlavička viditeľná, môžete predpokladať, že je viditeľná aj samotná odpoveď. Nemusíte testovať ani ukladať aktuálny stav viditeľnosti správy s odpoveďou. Do stavu Bundle s kľúčom "reply_text" prejde len samotný text správy.

Uložíte stav iba tých prvkov zobrazenia, ktoré sa môžu zmeniť po vytvorení aktivity. Ostatné prvky zobrazenia vo vašej aplikácii (Upraviť text, tlačidlo) je možné kedykoľvek znova vytvoriť z predvoleného rozloženia.

Všimnite si, že systém uloží stav niektorých prvkov zobrazenia, ako je obsah EditText.

2.2 Obnovenie stavu inštancie aktivity v onCreate()

Po uložení stavu inštancie aktivity ho musíte obnoviť aj pri opätovnom vytvorení aktivity. Môžete to urobiť buď v onCreate(), alebo implementáciou spätného volania onRestoreInstanceState(), ktoré sa volá po onStart() po vytvorení aktivity.

Väčšinu času je lepším miestom na obnovenie stavu aktivity onCreate(), aby sa zabezpečilo, že používateľské rozhranie vrátane stavu bude dostupné čo najskôr. Niekedy je vhodné to urobiť v onRestoreInstanceState() po vykonaní celej inicializácie alebo umožniť podtriedam rozhodnúť sa, či použiť vašu predvolenú implementáciu.

  1. V metóde onCreate() po inicializácii premenných View pomocou findViewById() pridajte test, aby ste sa uistili, že saveInstanceState nie je 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) {
}

Keď je vaša aktivita vytvorená, systém odovzdá stav Bundle onCreate() ako svoj jediný argument. Pri prvom volaní onCreate() a spustení vašej aplikácie je balík null – pri prvom spustení vašej aplikácie neexistuje žiadny stav. Následné volania onCreate() majú zväzok vyplnený údajmi, ktoré ste uložili v onSaveInstanceState().

  1. V rámci tejto kontroly získajte aktuálnu viditeľnosť (pravda alebo nepravda) z balíka pomocou kľúča „reply_visible“.
if (savedInstanceState != null) {
    boolean isVisible = 
                     savedInstanceState.getBoolean("reply_visible");
}
  1. Pod predchádzajúci riadok pridajte test pre premennú isVisible.
if (isVisible) {
}

Ak je v stave Bundle kľúč reply_visible (a isVisible je teda pravdivý), budete musieť obnoviť stav.

  1. Vo vnútri testu isVisible zviditeľnite hlavičku.
mReplyHeadTextView.setVisibility(View.VISIBLE);
  1. Získajte textovú odpoveď z balíka pomocou kľúča "reply_text" a nastavte textovú odpoveď tak, aby zobrazovala tento reťazec.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
  1. Zviditeľnite aj odpoveď TextView:
mReplyTextView.setVisibility(View.VISIBLE);
  1. Spustite aplikáciu. Skúste otočiť zariadenie alebo emulátor, aby ste sa uistili, že správa s odpoveďou (ak existuje) zostane na obrazovke po opätovnom vytvorení aktivity.

Kód riešenia úlohy 2

Nasledujúce útržky kódu zobrazujú kód riešenia pre túto úlohu.

Hlavná aktivita

Nasledujúce útržky kódu zobrazujú pridaný kód v MainActivity, ale nie celú triedu.

Metóda 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());
   }
}

Metóda 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ódovanie

Výzva: Vytvorte jednoduchú aplikáciu na nákupný zoznam s hlavnou aktivitou pre zoznam, ktorý používateľ vytvára, a druhou aktivitou pre zoznam bežných nákupných položiek.

  • Hlavná aktivita by mala obsahovať zoznam na zostavenie, ktorý by mal pozostávať z desiatich prázdnych prvkov TextView.
  • Tlačidlo Pridať položku v hlavnej aktivite spustí druhú aktivitu, ktorá obsahuje zoznam bežných nákupných položiek (syr, ryža, jablká atď.). Na zobrazenie položiek použite prvky tlačidiel.
  • Výber položky vráti používateľa do hlavnej aktivity a aktualizuje prázdny TextView tak, aby obsahoval vybratú položku.

Použite zámer na odovzdanie informácií z jednej aktivity do druhej. Uistite sa, že sa aktuálny stav nákupného zoznamu uloží, keď používateľ otočí zariadenie.

6. Zhrnutie

  • Životný cyklus aktivity je množina stavov, cez ktoré aktivita prechádza, počnúc prvým vytvorením a končiac, keď systém Android získa zdroje pre danú aktivitu.
  • Keď používateľ prechádza z jednej aktivity do druhej a vo vašej aplikácii aj mimo nej, každá aktivita sa presúva medzi stavmi životného cyklu aktivity.
  • Každý stav v životnom cykle aktivity má zodpovedajúcu metódu spätného volania, ktorú môžete prepísať vo svojej triede aktivity.
  • Metódy životného cyklu sú onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
  • Prepísanie metódy spätného volania životného cyklu vám umožňuje pridať správanie, ktoré nastane, keď vaša aktivita prejde do tohto stavu.
  • Metódy prepísania kostry môžete pridať do svojich tried v Android Studio pomocou Kód > Prepísať.
  • Zmeny konfigurácie zariadenia, napríklad rotácia, vedú k zničeniu aktivity a jej opätovnému vytvoreniu, ako keby bola nová.
  • Časť stavu aktivity sa pri zmene konfigurácie zachová, vrátane aktuálnych hodnôt prvkov EditText. Pre všetky ostatné údaje musíte tieto údaje výslovne uložiť sami.
  • Uložiť stav inštancie Activity v metóde onSaveInstanceState().
  • Údaje o stave inštancie sú uložené ako jednoduché páry kľúč/hodnota v balíku. Použite metódy Bundle na vloženie údajov a získanie údajov späť z Bundle.
  • Obnovte stav inštancie v onCreate(), čo je preferovaný spôsob, alebo onRestoreInstanceState(). Späť