Kako uporabljati življenjski cikel in stanje dejavnosti, Kako uporabljati življenjski cikel in stanje dejavnosti

1. Dobrodošli

Ta praktični laboratorij za kodiranje je del 1. enote: Začnite s tečajem Osnove razvijalca za Android (različica 2). Ta tečaj vam bo najbolj koristil, če boste delali skozi laboratorije kodiranja v zaporedju:

  • Za celoten seznam laboratorijev za kodiranje v tečaju si oglejte laboratorije za kodiranje za Android Developer Fundamentals (V2).
  • Za podrobnosti o tečaju, vključno s povezavami do vseh konceptualnih poglavij, aplikacij in diapozitivov, glejte Osnove razvijalca za Android (različica 2).

Uvod

V tej praksi boste izvedeli več o življenjskem ciklu dejavnosti. Življenjski cikel je nabor stanj, v katerih je lahko dejavnost v svoji celotni življenjski dobi, od trenutka, ko je ustvarjena, do trenutka, ko je uničena in sistem povrne njene vire. Ko uporabnik krmari med dejavnostmi v vaši aplikaciji (pa tudi v vašo aplikacijo in iz nje), dejavnosti prehajajo med različnimi stanji v svojih življenjskih ciklih.

Dvojne težave

Vsaka stopnja v življenjskem ciklu dejavnosti ima ustrezno metodo povratnega klica: onCreate(), onStart(), onPause() in tako naprej. Ko dejavnost spremeni stanje, se prikliče povezana metoda povratnega klica. Eno od teh metod ste že videli: onCreate(). Če preglasite katero koli metodo povratnega klica življenjskega cikla v svojih razredih dejavnosti, lahko spremenite privzeto vedenje dejavnosti kot odgovor na dejanja uporabnika ali sistema.

Stanje dejavnosti se lahko spremeni tudi kot odgovor na spremembe konfiguracije naprave, na primer ko uporabnik obrne napravo iz pokončnega v ležečega položaja. Ko pride do teh sprememb konfiguracije, se dejavnost uniči in znova ustvari v privzetem stanju, uporabnik pa lahko izgubi podatke, ki jih je vnesel v dejavnost. Da bi se izognili zmedi vaših uporabnikov, je pomembno, da svojo aplikacijo razvijete tako, da preprečite nepričakovano izgubo podatkov. Kasneje v tej praksi preizkusite spremembe konfiguracije in se naučite, kako ohraniti stanje dejavnosti kot odgovor na spremembe konfiguracije naprave in druge dogodke življenjskega cikla dejavnosti.

V tej praksi dodate izjave za beleženje v aplikacijo TwoActivities in med uporabo aplikacije opazujete spremembe življenjskega cikla dejavnosti. Nato začnete delati s temi spremembami in raziskovati, kako obravnavati uporabniške vnose pod temi pogoji.

Predpogoji

Morali bi biti sposobni:

  • Ustvarite in zaženite projekt aplikacije v Android Studiu .
  • Dodajte izjave dnevnika svoji aplikaciji in si te dnevnike oglejte v podoknu Logcat.
  • Razumeti in delati z dejavnostjo in namenom ter se počutiti udobno v interakciji z njima.

Kaj se boste naučili

  • Kako deluje življenjski cikel dejavnosti.
  • Ko se aktivnost začne, se začasno ustavi, ustavi in ​​uniči.
  • O metodah povratnega klica življenjskega cikla, povezanih s spremembami dejavnosti.
  • Učinek dejanj (kot so spremembe konfiguracije), ki lahko povzročijo dogodke življenjskega cikla dejavnosti.
  • Kako obdržati stanje aktivnosti med dogodki življenjskega cikla.

Kaj boš naredil

  • Aplikaciji TwoActivities dodajte kodo iz prejšnje praktične izvedbe, da implementirate različne povratne klice življenjskega cikla dejavnosti, da vključite stavke beleženja.
  • Opazujte spremembe stanja med izvajanjem vaše aplikacije in med interakcijo z vsako dejavnostjo v vaši aplikaciji.
  • Spremenite svojo aplikacijo, da ohrani stanje primerka dejavnosti, ki je nepričakovano znova ustvarjena kot odgovor na vedenje uporabnika ali spremembo konfiguracije v napravi.

2. Pregled aplikacije

V tej praksi dodate v aplikacijo TwoActivities . Aplikacija je videti in se obnaša približno enako kot v zadnjem laboratoriju za kodiranje. Vsebuje dve izvedbi dejavnosti in daje uporabniku možnost pošiljanja med njima. Spremembe, ki jih naredite v aplikaciji v tej praksi, ne bodo vplivale na njeno vidno uporabniško vedenje.

3. 3. Naloga 1: Dodajte povratne klice življenjskega cikla v TwoActivities

V tej nalogi boste implementirali vse metode povratnega klica življenjskega cikla dejavnosti za tiskanje sporočil v logcat, ko so te metode priklicane. Ta sporočila dnevnika vam bodo omogočila, da vidite, kdaj spremeni stanje življenjskega cikla dejavnosti in kako te spremembe stanja življenjskega cikla vplivajo na vašo aplikacijo med izvajanjem.

1.1 (Izbirno) Kopirajte projekt TwoActivities

Za naloge v tej praksi boste spremenili obstoječi projekt TwoActivities , ki ste ga zgradili v zadnji praksi. Če bi raje ohranili prejšnji projekt TwoActivities nedotaknjen, sledite korakom v Dodatku: Pripomočki, da naredite kopijo projekta.

1.2 Implementirajte povratne klice v MainActivity

  1. Odprite projekt TwoActivities v Android Studiu in odprite MainActivity v podoknu Projekt > Android.
  2. V metodi onCreate() dodajte naslednje izjave dnevnika:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
  1. Dodajte preglasitev za povratni klic onStart() z izjavo v dnevnik za ta dogodek:
@Override
public void onStart(){
    super.onStart();
    Log.d(LOG_TAG, "onStart");
}

Za bližnjico izberite Koda > Preglasi metode v Android Studiu. Prikaže se pogovorno okno z vsemi možnimi metodami, ki jih lahko preglasite v svojem razredu. Če na seznamu izberete eno ali več metod povratnega klica, se vstavi popolna predloga za te metode, vključno z zahtevanim klicem nadrazreda.

  1. Uporabite metodo onStart() kot predlogo za implementacijo povratnih klicev življenjskega cikla onPause(), onRestart(), onResume(), onStop() in onDestroy().

Vse metode povratnega klica imajo enake podpise (razen imena). Če kopirate in prilepite onStart(), da ustvarite te druge metode povratnega klica, ne pozabite posodobiti vsebine, da pokličete pravo metodo v nadrazredu, in zabeležiti pravilno metodo.

  1. Zaženite svojo aplikacijo.
  2. Kliknite zavihek Logcat na dnu Android Studio, da prikažete podokno Logcat. Videti bi morali tri sporočila dnevnika, ki prikazujejo tri stanja življenjskega cikla, skozi katera je dejavnost prešla, ko se je začela:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume

1.3 Implementirajte povratne klice življenjskega cikla v SecondActivity

Zdaj, ko ste implementirali metode povratnega klica življenjskega cikla za MainActivity, storite enako za SecondActivity.

  1. Odprite SecondActivity.
  2. Na vrh razreda dodajte konstanto za spremenljivko LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
  1. Drugi dejavnosti dodajte povratne klice življenjskega cikla in stavke dnevnika. (Metode povratnega klica lahko kopirate in prilepite iz MainActivity.)
  2. Dodajte stavek dnevnika metodi returnReply() tik pred metodo finish():
Log.d(LOG_TAG, "End SecondActivity");

1.4 Opazujte dnevnik med izvajanjem aplikacije**

  1. Zaženite svojo aplikacijo.
  2. Kliknite zavihek Logcat na dnu Android Studio, da prikažete podokno Logcat.
  3. V iskalno polje vnesite Aktivnost. Android logcat je lahko zelo dolg in natrpan. Ker spremenljivka LOG_TAG v vsakem razredu vsebuje besedi MainActivity ali SecondActivity, vam ta ključna beseda omogoča filtriranje dnevnika samo za stvari, ki vas zanimajo.

Dvojne težave

Preizkusite uporabo svoje aplikacije in upoštevajte dogodke življenjskega cikla, ki se zgodijo kot odgovor na različna dejanja. Poskusite zlasti te stvari:

  • Uporabite aplikacijo običajno (pošljite sporočilo, odgovorite z drugim sporočilom).
  • Z gumbom Nazaj se vrnite z druge dejavnosti na glavno dejavnost.
  • Uporabite puščico navzgor v vrstici z aplikacijami, da se vrnete iz druge dejavnosti na glavno dejavnost.
  • Zasukajte napravo na glavni in drugi dejavnosti ob različnih časih v aplikaciji in opazujte, kaj se dogaja v * dnevniku in na zaslonu.
  • Pritisnite gumb za pregled (kvadratni gumb na desni strani Domov) in zaprite aplikacijo (tapnite X).
  • Vrnite se na začetni zaslon in znova zaženite aplikacijo.

NASVET: Če izvajate svojo aplikacijo v emulatorju, lahko simulirate rotacijo s Control+F11 ali Control+Function+F11.

Šifra rešitve 1. naloge

Naslednji delčki kode prikazujejo kodo rešitve za prvo nalogo.

Glavna dejavnost

Naslednji delčki kode prikazujejo dodano kodo v MainActivity, vendar ne celotnega razreda.

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);
}

Druge metode življenjskega cikla:

@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");
}

SecondActivity

Naslednji delčki kode prikazujejo dodano kodo v SecondActivity, ne pa celotnega razreda.

Na vrhu razreda 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();
}

Druge metode življenjskega cikla:

Enako kot za MainActivity zgoraj.

4. 4. Naloga 2: Shranite in obnovite stanje instance Activity

Odvisno od sistemskih virov in vedenja uporabnika je lahko vsaka dejavnost v vaši aplikaciji uničena in rekonstruirana veliko pogosteje, kot si morda mislite.

To vedenje ste morda opazili v zadnjem razdelku, ko ste zasukali napravo ali emulator. Vrtenje naprave je en primer spremembe konfiguracije naprave. Čeprav je rotacija najpogostejša, vse spremembe konfiguracije povzročijo, da se trenutna dejavnost uniči in ponovno ustvari, kot da bi bila nova. Če tega vedenja ne upoštevate v svoji kodi, se lahko ob spremembi konfiguracije vaša postavitev dejavnosti povrne na privzeti videz in začetne vrednosti, vaši uporabniki pa lahko izgubijo svoje mesto, svoje podatke ali stanje svojega napredka v vašo aplikacijo.

Stanje vsake dejavnosti je shranjeno kot nabor parov ključ/vrednost v objektu Bundle, imenovanem stanje primerka dejavnosti. Sistem shrani informacije o privzetem stanju v sveženj stanja primerka, tik preden je dejavnost ustavljena, in ta sveženj posreduje novemu primerku dejavnosti za obnovitev.

Če želite preprečiti izgubo podatkov v dejavnosti, ko je ta nepričakovano uničena in ponovno ustvarjena, morate implementirati metodo onSaveInstanceState(). Sistem pokliče to metodo za vašo dejavnost (med onPause() in onStop()), ko obstaja možnost, da se aktivnost uniči in ponovno ustvari.

Podatki, ki jih shranite v stanju primerka, so specifični samo za ta primerek te specifične dejavnosti med trenutno sejo aplikacije. Ko ustavite in znova zaženete novo sejo aplikacije, se stanje primerka dejavnosti izgubi in dejavnost se vrne v privzeti videz. Če morate shraniti uporabniške podatke med sejami aplikacije, uporabite skupne nastavitve ali bazo podatkov. O obeh boste izvedeli v kasnejši praksi.

2.1 Shranite stanje primerka dejavnosti z onSaveInstanceState()

Morda ste opazili, da vrtenje naprave sploh ne vpliva na stanje druge dejavnosti. To je zato, ker sta postavitev in stanje druge dejavnosti ustvarjena iz postavitve in namena, ki ju je aktiviral. Tudi če je dejavnost ponovno ustvarjena, je namen še vedno tam in podatki v tem namenu se še vedno uporabljajo vsakič, ko se pokliče metoda onCreate() v drugi dejavnosti.

Poleg tega boste morda opazili, da se v vsaki dejavnosti vse besedilo, ki ste ga vnesli v elemente sporočila ali odgovora EditText, ohrani tudi, ko napravo obrnete. To je zato, ker se informacije o stanju nekaterih elementov pogleda v vaši postavitvi samodejno shranijo med spremembami konfiguracije in trenutna vrednost EditText je eden od teh primerov.

Torej so edino stanje dejavnosti, ki vas zanima, elementi TextView za glavo odgovora in besedilo odgovora v glavni dejavnosti. Oba elementa TextView sta privzeto nevidna; prikažejo se šele, ko iz druge dejavnosti pošljete sporočilo nazaj v glavno dejavnost.

V tej nalogi dodate kodo za ohranitev stanja primerka teh dveh elementov TextView z uporabo onSaveInstanceState().

  1. Odprite MainActivity.
  2. Dodajte to okvirno implementacijo onSaveInstanceState() v dejavnost ali uporabite Koda > Preglasi metode, da vstavite okvirno preglasitev.
@Override
public void onSaveInstanceState(Bundle outState) {
          super.onSaveInstanceState(outState);
}
  1. Preverite, ali je glava trenutno vidna, in če je, to stanje vidnosti vnesite v paket stanja z metodo putBoolean() in ključem "reply_visible".
 if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
        outState.putBoolean("reply_visible", true);
    }

Ne pozabite, da sta glava in besedilo odgovora označena kot nevidna, dokler ni odgovora iz druge dejavnosti. Če je glava vidna, potem obstajajo podatki o odgovoru, ki jih je treba shraniti. Upoštevajte, da nas zanima le to stanje vidnosti — dejanskega besedila glave ni treba shraniti, ker se to besedilo nikoli ne spremeni.

  1. Znotraj istega preverjanja dodajte besedilo odgovora v sveženj.
outState.putString("reply_text",mReplyTextView.getText().toString());

Če je glava vidna, lahko domnevate, da je viden tudi sam odgovor. Ni vam treba preizkusiti ali shraniti trenutnega stanja vidnosti odgovora. Samo dejansko besedilo sporočila gre v stanje Bundle s ključem "reply_text".

Shranite stanje samo tistih elementov pogleda, ki se lahko spremenijo, ko je aktivnost ustvarjena. Druge elemente View v vaši aplikaciji (EditText, Button) lahko kadar koli znova ustvarite iz privzete postavitve.

Upoštevajte, da bo sistem shranil stanje nekaterih elementov pogleda, kot je vsebina EditText.

2.2 Obnovite stanje primerka Activity v onCreate()

Ko shranite stanje primerka dejavnosti, ga morate tudi obnoviti, ko je dejavnost znova ustvarjena. To lahko storite v onCreate() ali z implementacijo povratnega klica onRestoreInstanceState(), ki se pokliče za onStart(), potem ko je aktivnost ustvarjena.

Večino časa je boljše mesto za obnovitev stanja dejavnosti v onCreate(), da zagotovite, da je uporabniški vmesnik, vključno s stanjem, na voljo čim prej. Včasih je priročno, da to storite v onRestoreInstanceState(), potem ko je bila opravljena vsa inicializacija, ali da dovolite podrazredom, da se odločijo, ali bodo uporabili vašo privzeto izvedbo.

  1. V metodi onCreate(), potem ko so spremenljivke View inicializirane z findViewById(), dodajte preizkus, da se prepričate, da savedInstanceState ni ničelna.
// 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) {
}

Ko je vaša dejavnost ustvarjena, sistem kot edini argument posreduje sveženj stanja onCreate(). Ko se prvič pokliče onCreate() in se vaša aplikacija zažene, je sveženj ničen – ob prvem zagonu aplikacije ni obstoječega stanja. Pri nadaljnjih klicih onCreate() je sveženj zapolnjen s podatki, ki ste jih shranili v onSaveInstanceState().

  1. Znotraj tega preverjanja pridobite trenutno vidnost (true ali false) iz svežnja s ključem "reply_visible".
if (savedInstanceState != null) {
    boolean isVisible = 
                     savedInstanceState.getBoolean("reply_visible");
}
  1. Dodajte preizkus pod prejšnjo vrstico za spremenljivko isVisible.
if (isVisible) {
}

Če je v svežnju stanja ključ reply_visible (in je torej isVisible resničen), boste morali stanje obnoviti.

  1. Znotraj testa isVisible naredite glavo vidno.
mReplyHeadTextView.setVisibility(View.VISIBLE);
  1. Pridobite besedilno odgovorno sporočilo iz paketa s ključem "reply_text" in nastavite odgovor TextView, da prikaže ta niz.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
  1. Naj bo viden tudi odgovor TextView:
mReplyTextView.setVisibility(View.VISIBLE);
  1. Zaženite aplikacijo. Poskusite zavrteti napravo ali emulator, da zagotovite, da sporočilo z odgovorom (če obstaja) ostane na zaslonu, potem ko je aktivnost znova ustvarjena.

Šifra rešitve 2. naloge

Naslednji izrezki kode prikazujejo kodo rešitve za to nalogo.

Glavna dejavnost

Naslednji delčki kode prikazujejo dodano kodo v MainActivity, vendar ne celotnega razreda.

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);
       }
   }
}

Celoten projekt:

Projekt Android Studio: TwoActivitiesLifecycle

5. Kodiranje

Izziv: ustvarite preprosto aplikacijo nakupovalnega seznama z glavno dejavnostjo za seznam, ki ga sestavlja uporabnik, in drugo dejavnostjo za seznam pogostih nakupovalnih artiklov.

  • Glavna dejavnost mora vsebovati seznam za izdelavo, ki mora biti sestavljen iz desetih praznih elementov TextView.
  • Gumb Dodaj artikel v glavni dejavnosti zažene drugo aktivnost, ki vsebuje seznam običajnih nakupovalnih artiklov (sir, riž, jabolka itd.). Za prikaz elementov uporabite elemente gumbov.
  • Izbira elementa vrne uporabnika k glavni dejavnosti in posodobi prazen TextView, da vključi izbrani element.

Uporabite namen za prenos informacij iz ene dejavnosti v drugo. Prepričajte se, da je trenutno stanje nakupovalnega seznama shranjeno, ko uporabnik obrne napravo.

6. Povzetek

  • Življenjski cikel dejavnosti je nabor stanj, skozi katere migrira dejavnost, ki se začne, ko je prvič ustvarjena, in konča, ko sistem Android povrne vire za to dejavnost.
  • Ko uporabnik krmari od ene dejavnosti do druge ter znotraj in zunaj vaše aplikacije, se vsaka dejavnost premika med stanji v življenjskem ciklu dejavnosti.
  • Vsako stanje v življenjskem ciklu dejavnosti ima ustrezno metodo povratnega klica, ki jo lahko preglasite v razredu dejavnosti.
  • Metode življenjskega cikla so onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
  • Preglasitev metode povratnega klica življenjskega cikla vam omogoča, da dodate vedenje, ki se pojavi, ko vaša dejavnost preide v to stanje.
  • Svojim razredom v Android Studiu lahko dodate metode preglasitve okostja s Kodo > Preglasi.
  • Spremembe konfiguracije naprave, kot je rotacija, povzročijo, da se dejavnost uniči in znova ustvari, kot da bi bila nova.
  • Del stanja dejavnosti se ob spremembi konfiguracije ohrani, vključno s trenutnimi vrednostmi elementov EditText. Za vse druge podatke morate te podatke izrecno shraniti sami.
  • Shrani stanje primerka dejavnosti v metodi onSaveInstanceState().
  • Podatki o stanju primerka so shranjeni kot preprosti pari ključ/vrednost v svežnju. Uporabite metode Bundle za vstavljanje podatkov v sveženj in pridobivanje podatkov nazaj iz njega.
  • Obnovite stanje primerka v onCreate(), kar je prednostni način, ali onRestoreInstanceState(). Nazaj