Cum se utilizează Ciclul de viață și starea activității

1. Bun venit

Acest laborator de cod practic face parte din Unitatea 1: Începeți în cursul Fundamentele dezvoltatorilor Android (Versiunea 2). Veți obține cea mai mare valoare din acest curs dacă lucrați prin laboratoarele de cod în secvență:

  • Pentru lista completă a laboratoarelor de cod din curs, consultați Noțiunile fundamentale pentru dezvoltatori Android Codelabs (V2).
  • Pentru detalii despre curs, inclusiv linkuri către toate capitolele de concept, aplicațiile și diapozitivele, consultați Fundamentele dezvoltatorilor Android (versiunea 2).

Introducere

În această practică veți afla mai multe despre ciclul de viață al activității. Ciclul de viață este ansamblul de stări în care se poate afla o activitate pe toată durata ei de viață, de la momentul în care este creată până la momentul în care este distrusă și sistemul își revendică resursele. Pe măsură ce un utilizator navighează între activitățile din aplicația dvs. (precum și în și în afara aplicației), activitățile trec între diferite stări din ciclurile lor de viață.

dublu necaz

Fiecare etapă din ciclul de viață al unei activități are o metodă de apel invers corespunzătoare: onCreate(), onStart(), onPause() și așa mai departe. Când o activitate își schimbă starea, este invocată metoda de apel invers asociată. Ați văzut deja una dintre aceste metode: onCreate(). Prin suprascrierea oricăreia dintre metodele de apel invers ciclului de viață din clasele dvs. de activitate, puteți modifica comportamentul implicit al activității ca răspuns la acțiunile utilizatorului sau ale sistemului.

Starea activității se poate modifica și ca răspuns la modificările configurației dispozitivului, de exemplu atunci când utilizatorul rotește dispozitivul de la portret la peisaj. Când au loc aceste modificări de configurare, activitatea este distrusă și recreată în starea sa implicită, iar utilizatorul poate pierde informațiile pe care le-a introdus în activitate. Pentru a evita confuzia utilizatorilor, este important să vă dezvoltați aplicația pentru a preveni pierderea neașteptată a datelor. Mai târziu, în această practică, veți experimenta modificări de configurare și învățați cum să păstrați starea unei activități ca răspuns la modificările configurației dispozitivului și la alte evenimente din ciclul de viață al activității.

În această practică, adăugați declarații de înregistrare în aplicația TwoActivities și observați modificările ciclului de viață al activității pe măsură ce utilizați aplicația. Apoi începeți să lucrați cu aceste modificări și să explorați cum să gestionați intrarea utilizatorului în aceste condiții.

Cerințe preliminare

Ar trebui să poți:

  • Creați și rulați un proiect de aplicație în Android Studio .
  • Adăugați declarații de jurnal în aplicația dvs. și vizualizați acele jurnale în panoul Logcat.
  • Înțelegeți și lucrați cu o activitate și o intenție și să fiți confortabil să interacționați cu acestea.

Ce vei învăța

  • Cum funcționează ciclul de viață al activității.
  • Când o activitate începe, se întrerupe, se oprește și este distrusă.
  • Despre metodele de apel invers ciclului de viață asociate cu modificările activității.
  • Efectul acțiunilor (cum ar fi modificările configurației) care pot duce la evenimente ciclului de viață al activității.
  • Cum să păstrați starea activității pe parcursul evenimentelor ciclului de viață.

Ce vei face

  • Adăugați cod în aplicația TwoActivities din practica anterioară pentru a implementa diferitele apeluri ale ciclului de viață al activității pentru a include instrucțiuni de înregistrare.
  • Observați schimbările de stare pe măsură ce aplicația dvs. rulează și pe măsură ce interacționați cu fiecare activitate din aplicație.
  • Modificați aplicația pentru a păstra starea instanței unei activități care este recreată în mod neașteptat ca răspuns la comportamentul utilizatorului sau la modificarea configurației pe dispozitiv.

2. Prezentare generală a aplicației

În această practică, adăugați la aplicația TwoActivities . Aplicația arată și se comportă aproximativ la fel ca în ultimul laborator de codare. Conține două implementări de activitate și oferă utilizatorului posibilitatea de a trimite între ele. Modificările pe care le faceți aplicației în această practică nu vor afecta comportamentul vizibil al utilizatorului.

3. 3. Sarcina 1: Adăugați apeluri inverse ciclului de viață la TwoActivities

În această sarcină, veți implementa toate metodele de apel invers ciclului de viață al activității pentru a imprima mesaje către logcat atunci când acele metode sunt invocate. Aceste mesaje de jurnal vă vor permite să vedeți când se schimbă starea ciclului de viață al activității și cum afectează aceste modificări ale stării ciclului de viață aplicația dvs. pe măsură ce rulează.

1.1 (Opțional) Copiați proiectul TwoActivities

Pentru sarcinile din această practică, veți modifica proiectul TwoActivities existent pe care l-ați construit în ultima practică. Dacă preferați să păstrați intact proiectul TwoActivities anterior, urmați pașii din Anexă: Utilități pentru a face o copie a proiectului.

1.2 Implementați apeluri înapoi în MainActivity

  1. Deschideți proiectul TwoActivities în Android Studio și deschideți MainActivity în panoul Proiect > Android.
  2. În metoda onCreate(), adăugați următoarele instrucțiuni de jurnal:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
  1. Adăugați o suprascriere pentru apel invers onStart(), cu o declarație în jurnal pentru acel eveniment:
@Override
public void onStart(){
    super.onStart();
    Log.d(LOG_TAG, "onStart");
}

Pentru o comandă rapidă, selectați Cod > Suprascrierea metodelor în Android Studio. Apare un dialog cu toate metodele posibile pe care le puteți modifica în clasa dvs. Alegerea uneia sau mai multor metode de apel invers din listă inserează un șablon complet pentru acele metode, inclusiv apelul necesar la superclasă.

  1. Utilizați metoda onStart() ca șablon pentru a implementa apelurile ciclului de viață onPause(), onRestart(), onResume(), onStop() și onDestroy()

Toate metodele de apel invers au aceleași semnături (cu excepția numelui). Dacă copiați și inserați onStart() pentru a crea aceste alte metode de apel invers, nu uitați să actualizați conținutul pentru a apela metoda potrivită în superclasă și pentru a înregistra metoda corectă.

  1. Rulați aplicația.
  2. Faceți clic pe fila Logcat din partea de jos a Android Studio pentru a afișa panoul Logcat. Ar trebui să vedeți trei mesaje de jurnal care arată cele trei stări ale ciclului de viață prin care a trecut activitatea, așa cum a început:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume

1.3 Implementați apelurile ciclului de viață în SecondActivity

Acum că ați implementat metodele de apel invers ciclului de viață pentru MainActivity, faceți același lucru pentru SecondActivity.

  1. Deschideți SecondActivity.
  2. În partea de sus a clasei, adăugați o constantă pentru variabila LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
  1. Adăugați apelurile ciclului de viață și declarațiile de jurnal la a doua activitate. (Puteți Copiați și Lipiți metodele de apel invers din MainActivity.)
  2. Adăugați o instrucțiune de jurnal la metoda returnReply() chiar înainte de metoda finish():
Log.d(LOG_TAG, "End SecondActivity");

1.4 Observați jurnalul în timp ce aplicația rulează**

  1. Rulați aplicația.
  2. Faceți clic pe fila Logcat din partea de jos a Android Studio pentru a afișa panoul Logcat.
  3. Introduceți Activitate în caseta de căutare. Logcat-ul Android poate fi foarte lung și aglomerat. Deoarece variabila LOG_TAG din fiecare clasă conține fie cuvintele MainActivity, fie SecondActivity, acest cuvânt cheie vă permite să filtrați jurnalul numai pentru lucrurile care vă interesează.

dublu necaz

Experimentați folosind aplicația dvs. și rețineți că evenimentele ciclului de viață care apar ca răspuns la diferite acțiuni. În special, încercați aceste lucruri:

  • Utilizați aplicația în mod normal (trimiteți un mesaj, răspundeți cu un alt mesaj).
  • Utilizați butonul Înapoi pentru a reveni de la a doua activitate la activitatea principală.
  • Utilizați săgeata în sus din bara de aplicații pentru a reveni de la a doua activitate la activitatea principală.
  • Rotiți dispozitivul atât pe activitatea principală, cât și pe cea de-a doua, în momente diferite din aplicația dvs. și observați ce se întâmplă în * jurnal și pe ecran.
  • Apăsați butonul de prezentare generală (butonul pătrat din dreapta Home) și închideți aplicația (atingeți X).
  • Reveniți la ecranul de pornire și reporniți aplicația.

SFAT: dacă rulați aplicația într-un emulator, puteți simula rotația cu Control+F11 sau Control+Function+F11.

Codul soluției pentru sarcina 1

Următoarele fragmente de cod arată codul soluției pentru prima sarcină.

Activitatea principală

Următoarele fragmente de cod arată codul adăugat în MainActivity, dar nu întreaga clasă.

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

Celelalte metode de ciclu de viață:

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

A doua activitate

Următoarele fragmente de cod arată codul adăugat în SecondActivity, dar nu întreaga clasă.

În partea de sus a clasei 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();
}

Celelalte metode de ciclu de viață:

La fel ca pentru MainActivity, mai sus.

4. 4. Sarcina 2: Salvați și restaurați starea instanței de activitate

În funcție de resursele sistemului și de comportamentul utilizatorului, fiecare activitate din aplicația dvs. poate fi distrusă și reconstruită mult mai des decât ați crede.

Este posibil să fi observat acest comportament în ultima secțiune când ați rotit dispozitivul sau emulatorul. Rotirea dispozitivului este un exemplu de modificare a configurației dispozitivului. Deși rotația este cea mai comună, toate modificările de configurare au ca rezultat distrugerea și recrearea activității curente ca și cum ar fi nouă. Dacă nu țineți cont de acest comportament în codul dvs., atunci când are loc o modificare a configurației, aspectul activității dvs. poate reveni la aspectul implicit și la valorile inițiale, iar utilizatorii dvs. își pot pierde locul, datele sau starea progresului lor în aplicația dvs.

Starea fiecărei activități este stocată ca un set de perechi cheie/valoare într-un obiect Bundle numit starea instanței Activitate. Sistemul salvează informații despre starea implicită în pachetul de stare a instanței chiar înainte ca Activitatea să fie oprită și transmite acel pachet la noua instanță de activitate pentru a fi restaurat.

Pentru a evita pierderea datelor dintr-o Activitate atunci când aceasta este distrusă și recreată în mod neașteptat, trebuie să implementați metoda onSaveInstanceState(). Sistemul apelează această metodă în activitatea dvs. (între onPause() și onStop()) atunci când există posibilitatea ca Activitatea să fie distrusă și recreată.

Datele pe care le salvați în starea instanței sunt specifice numai acestei instanțe a acestei activități specifice în timpul sesiunii curente a aplicației. Când opriți și reporniți o nouă sesiune de aplicație, starea instanței de activitate se pierde și activitatea revine la aspectul implicit. Dacă trebuie să salvați datele utilizatorului între sesiunile de aplicație, utilizați preferințe partajate sau o bază de date. Veți afla despre ambele acestea într-o practică ulterioară.

2.1 Salvați starea instanței de activitate cu onSaveInstanceState()

Este posibil să fi observat că rotirea dispozitivului nu afectează deloc starea celei de-a doua activități. Acest lucru se datorează faptului că al doilea aspect și stare de activitate sunt generate din aspect și intenția care a activat-o. Chiar dacă Activitatea este recreată, Intenția este încă acolo și datele din acea Intenție sunt încă folosite de fiecare dată când este apelată metoda onCreate() din a doua Activitate.

În plus, este posibil să observați că în fiecare activitate, orice text pe care l-ați introdus în elementele EditText mesaj sau răspuns este reținut chiar și atunci când dispozitivul este rotit. Acest lucru se datorează faptului că informațiile de stare ale unora dintre elementele View din aspectul dvs. sunt salvate automat în timpul modificărilor de configurare, iar valoarea curentă a unui EditText este unul dintre aceste cazuri.

Deci, singura stare de activitate care vă interesează sunt elementele TextView pentru antetul de răspuns și textul de răspuns din Activitatea principală. Ambele elemente TextView sunt invizibile implicit; ele apar numai după ce trimiteți un mesaj înapoi la Activitatea principală din a doua Activitate.

În această sarcină adăugați cod pentru a păstra starea instanței acestor două elemente TextView folosind onSaveInstanceState().

  1. Deschide MainActivity.
  2. Adăugați această implementare schelet a onSaveInstanceState() la activitate sau utilizați Code > Override Methods pentru a insera o schelet override.
@Override
public void onSaveInstanceState(Bundle outState) {
          super.onSaveInstanceState(outState);
}
  1. Verificați dacă antetul este vizibil în prezent și, dacă da, puneți acea stare de vizibilitate în starea Bundle cu metoda putBoolean() și cheia „reply_visible”.
 if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
        outState.putBoolean("reply_visible", true);
    }

Rețineți că antetul de răspuns și textul sunt marcate invizibile până când există un răspuns de la a doua activitate. Dacă antetul este vizibil, atunci există date de răspuns care trebuie salvate. Rețineți că ne interesează doar acea stare de vizibilitate - textul real al antetului nu trebuie să fie salvat, deoarece acel text nu se schimbă niciodată.

  1. În cadrul aceleiași verificări, adăugați textul de răspuns în pachet.
outState.putString("reply_text",mReplyTextView.getText().toString());

Dacă antetul este vizibil, puteți presupune că mesajul de răspuns în sine este și el vizibil. Nu trebuie să testați sau să salvați starea curentă de vizibilitate a mesajului de răspuns. Doar textul real al mesajului intră în pachetul de stare cu cheia „reply_text”.

Salvați starea doar a acelor elemente de vizualizare care s-ar putea modifica după crearea activității. Celelalte elemente View din aplicația dvs. (EditText, Button) pot fi recreate din aspectul implicit în orice moment.

Rețineți că sistemul va salva starea unor elemente View, cum ar fi conținutul EditText.

2.2 Restaurați starea instanței de activitate în onCreate()

După ce ați salvat starea instanței de activitate, trebuie să o restabiliți și atunci când activitatea este recreată. Puteți face acest lucru fie în onCreate(), fie prin implementarea apelului onRestoreInstanceState(), care este apelat după onStart() după crearea activității.

De cele mai multe ori, locul mai bun pentru a restabili starea Activitate este în onCreate(), pentru a vă asigura că interfața de utilizare, inclusiv starea, este disponibilă cât mai curând posibil. Uneori este convenabil să o faceți în onRestoreInstanceState() după ce toată inițializarea a fost făcută sau să permiteți subclaselor să decidă dacă să utilizeze implementarea implicită.

  1. În metoda onCreate(), după ce variabilele View sunt inițializate cu findViewById(), adăugați un test pentru a vă asigura că savedInstanceState nu este nul.
// 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) {
}

Când activitatea dvs. este creată, sistemul transmite pachetul de stare la onCreate() ca singur argument. Prima dată când onCreate() este apelat și aplicația dvs. pornește, pachetul este nul - nu există nicio stare existentă la prima pornire a aplicației. Apelurile ulterioare la onCreate() au un pachet populat cu datele pe care le-ați stocat în onSaveInstanceState().

  1. În cadrul acelei verificări, scoateți vizibilitatea curentă (adevărată sau falsă) din pachet cu cheia „reply_visible”.
if (savedInstanceState != null) {
    boolean isVisible = 
                     savedInstanceState.getBoolean("reply_visible");
}
  1. Adăugați un test sub acea linie anterioară pentru variabila isVisible.
if (isVisible) {
}

Dacă există o cheie reply_visible în pachetul de stare (și, prin urmare, isVisible este adevărat), va trebui să restabiliți starea.

  1. În interiorul testului isVisible, faceți antetul vizibil.
mReplyHeadTextView.setVisibility(View.VISIBLE);
  1. Obțineți mesajul de răspuns text din pachet cu cheia „reply_text” și setați răspunsul TextView pentru a afișa acel șir.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
  1. Faceți și răspunsul TextView vizibil:
mReplyTextView.setVisibility(View.VISIBLE);
  1. Rulați aplicația. Încercați să rotiți dispozitivul sau emulatorul pentru a vă asigura că mesajul de răspuns (dacă există unul) rămâne pe ecran după recrearea activității.

Codul soluției pentru sarcina 2

Următoarele fragmente de cod arată codul soluției pentru această sarcină.

Activitatea principală

Următoarele fragmente de cod arată codul adăugat în MainActivity, dar nu întreaga clasă.

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

Proiectul complet:

Proiect Android Studio: TwoActivitiesLifecycle

5. Codificare

Provocare: creați o aplicație simplă pentru lista de cumpărături cu o activitate principală pentru lista pe care o creează utilizatorul și o a doua activitate pentru o listă de articole comune de cumpărături.

  • Activitatea principală ar trebui să conțină lista de construit, care ar trebui să fie alcătuită din zece elemente TextView goale.
  • Un buton Adăugare articol de pe activitatea principală lansează o a doua activitate care conține o listă de articole comune de cumpărături (brânză, orez, mere și așa mai departe). Utilizați elemente Button pentru a afișa elementele.
  • Alegerea unui articol readuce utilizatorul la activitatea principală și actualizează un TextView gol pentru a include elementul ales.

Utilizați o intenție pentru a transmite informații de la o activitate la alta. Asigurați-vă că starea curentă a listei de cumpărături este salvată atunci când utilizatorul rotește dispozitivul.

6. Rezumat

  • Ciclul de viață al activității este un set de stări prin care migrează o activitate, începând când este creată pentru prima dată și se termină când sistemul Android recuperează resursele pentru acea activitate.
  • Pe măsură ce utilizatorul navighează de la o activitate la alta și în interiorul și în afara aplicației dvs., fiecare activitate se deplasează între stările din ciclul de viață al activității.
  • Fiecare stare din ciclul de viață al activității are o metodă de apel invers corespunzătoare pe care o puteți înlocui în clasa dvs. de activitate.
  • Metodele ciclului de viață sunt onCreate(), onStart(), onPause(), onRestart(), onResume(), onStop(), onDestroy().
  • Suprascrierea unei metode de apel invers ciclului de viață vă permite să adăugați un comportament care apare atunci când Activitatea dvs. trece în acea stare.
  • Puteți adăuga metode de înlocuire schelet la clasele dvs. în Android Studio cu Cod > Suprascriere.
  • Modificările configurației dispozitivului, cum ar fi rotația, duc la distrugerea și recrearea activității ca și cum ar fi nouă.
  • O parte din starea Activitate este păstrată la o modificare a configurației, inclusiv valorile curente ale elementelor EditText. Pentru toate celelalte date, trebuie să salvați în mod explicit datele respective.
  • Starea instanței de salvare a activității în metoda onSaveInstanceState().
  • Datele de stare ale instanței sunt stocate ca simple perechi cheie/valoare într-un pachet. Utilizați metodele Bundle pentru a introduce date și pentru a le extrage înapoi din Bundle.
  • Restaurați starea instanței în onCreate(), care este modalitatea preferată, sau onRestoreInstanceState(). Spate
,

1. Bun venit

Acest laborator de cod practic face parte din Unitatea 1: Începeți în cursul Fundamentele dezvoltatorilor Android (Versiunea 2). Veți obține cea mai mare valoare din acest curs dacă lucrați prin laboratoarele de cod în secvență:

  • Pentru lista completă a laboratoarelor de cod din curs, consultați Noțiunile fundamentale pentru dezvoltatori Android Codelabs (V2).
  • Pentru detalii despre curs, inclusiv linkuri către toate capitolele de concept, aplicațiile și diapozitivele, consultați Fundamentele dezvoltatorilor Android (versiunea 2).

Introducere

În această practică veți afla mai multe despre ciclul de viață al activității. Ciclul de viață este ansamblul de stări în care se poate afla o activitate pe toată durata ei de viață, de la momentul în care este creată până la momentul în care este distrusă și sistemul își revendică resursele. Pe măsură ce un utilizator navighează între activitățile din aplicația dvs. (precum și în și în afara aplicației), activitățile trec între diferite stări din ciclurile lor de viață.

dublu necaz

Fiecare etapă din ciclul de viață al unei activități are o metodă de apel invers corespunzătoare: onCreate(), onStart(), onPause() și așa mai departe. Când o activitate își schimbă starea, este invocată metoda de apel invers asociată. Ați văzut deja una dintre aceste metode: onCreate(). Prin suprascrierea oricăreia dintre metodele de apel invers ciclului de viață din clasele dvs. de activitate, puteți modifica comportamentul implicit al activității ca răspuns la acțiunile utilizatorului sau ale sistemului.

Starea activității se poate modifica și ca răspuns la modificările configurației dispozitivului, de exemplu atunci când utilizatorul rotește dispozitivul de la portret la peisaj. Când au loc aceste modificări de configurare, activitatea este distrusă și recreată în starea sa implicită, iar utilizatorul poate pierde informațiile pe care le-a introdus în activitate. Pentru a evita confuzia utilizatorilor, este important să vă dezvoltați aplicația pentru a preveni pierderea neașteptată a datelor. Mai târziu, în această practică, veți experimenta modificări de configurare și învățați cum să păstrați starea unei activități ca răspuns la modificările configurației dispozitivului și la alte evenimente din ciclul de viață al activității.

În această practică, adăugați declarații de înregistrare în aplicația TwoActivities și observați modificările ciclului de viață al activității pe măsură ce utilizați aplicația. Apoi începeți să lucrați cu aceste modificări și să explorați cum să gestionați intrarea utilizatorului în aceste condiții.

Cerințe preliminare

Ar trebui să poți:

  • Creați și rulați un proiect de aplicație în Android Studio .
  • Adăugați declarații de jurnal în aplicația dvs. și vizualizați acele jurnale în panoul Logcat.
  • Înțelegeți și lucrați cu o activitate și o intenție și să fiți confortabil să interacționați cu acestea.

Ce vei învăța

  • Cum funcționează ciclul de viață al activității.
  • Când o activitate începe, se întrerupe, se oprește și este distrusă.
  • Despre metodele de apel invers ciclului de viață asociate cu modificările activității.
  • Efectul acțiunilor (cum ar fi modificările configurației) care pot duce la evenimente ciclului de viață al activității.
  • Cum să păstrați starea activității pe parcursul evenimentelor ciclului de viață.

Ce vei face

  • Adăugați cod în aplicația TwoActivities din practica anterioară pentru a implementa diferitele apeluri ale ciclului de viață al activității pentru a include instrucțiuni de înregistrare.
  • Observați schimbările de stare pe măsură ce aplicația dvs. rulează și pe măsură ce interacționați cu fiecare activitate din aplicație.
  • Modificați aplicația pentru a păstra starea instanței unei activități care este recreată în mod neașteptat ca răspuns la comportamentul utilizatorului sau la modificarea configurației pe dispozitiv.

2. Prezentare generală a aplicației

În această practică, adăugați la aplicația TwoActivities . Aplicația arată și se comportă aproximativ la fel ca în ultimul laborator de codare. Conține două implementări de activitate și oferă utilizatorului posibilitatea de a trimite între ele. Modificările pe care le faceți aplicației în această practică nu vor afecta comportamentul vizibil al utilizatorului.

3. 3. Sarcina 1: Adăugați apeluri inverse ciclului de viață la TwoActivities

În această sarcină, veți implementa toate metodele de apel invers ciclului de viață al activității pentru a imprima mesaje către logcat atunci când acele metode sunt invocate. Aceste mesaje de jurnal vă vor permite să vedeți când se schimbă starea ciclului de viață al activității și cum afectează aceste modificări ale stării ciclului de viață aplicația dvs. pe măsură ce rulează.

1.1 (Opțional) Copiați proiectul TwoActivities

Pentru sarcinile din această practică, veți modifica proiectul TwoActivities existent pe care l-ați construit în ultima practică. Dacă preferați să păstrați intact proiectul TwoActivities anterior, urmați pașii din Anexă: Utilități pentru a face o copie a proiectului.

1.2 Implementați apeluri înapoi în MainActivity

  1. Deschideți proiectul TwoActivities în Android Studio și deschideți MainActivity în panoul Proiect > Android.
  2. În metoda onCreate(), adăugați următoarele instrucțiuni de jurnal:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
  1. Adăugați o suprascriere pentru apel invers onStart(), cu o declarație în jurnal pentru acel eveniment:
@Override
public void onStart(){
    super.onStart();
    Log.d(LOG_TAG, "onStart");
}

Pentru o comandă rapidă, selectați Cod > Suprascrierea metodelor în Android Studio. Apare un dialog cu toate metodele posibile pe care le puteți modifica în clasa dvs. Alegerea uneia sau mai multor metode de apel invers din listă inserează un șablon complet pentru acele metode, inclusiv apelul necesar la superclasă.

  1. Utilizați metoda onStart() ca șablon pentru a implementa apelurile ciclului de viață onPause(), onRestart(), onResume(), onStop() și onDestroy()

Toate metodele de apel invers au aceleași semnături (cu excepția numelui). Dacă copiați și inserați onStart() pentru a crea aceste alte metode de apel invers, nu uitați să actualizați conținutul pentru a apela metoda potrivită în superclasă și pentru a înregistra metoda corectă.

  1. Rulați aplicația.
  2. Faceți clic pe fila Logcat din partea de jos a Android Studio pentru a afișa panoul Logcat. Ar trebui să vedeți trei mesaje de jurnal care arată cele trei stări ale ciclului de viață prin care a trecut activitatea, așa cum a început:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume

1.3 Implementați apelurile ciclului de viață în SecondActivity

Acum că ați implementat metodele de apel invers ciclului de viață pentru MainActivity, faceți același lucru pentru SecondActivity.

  1. Deschideți SecondActivity.
  2. În partea de sus a clasei, adăugați o constantă pentru variabila LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
  1. Adăugați apelurile ciclului de viață și declarațiile de jurnal la a doua activitate. (Puteți Copiați și Lipiți metodele de apel invers din MainActivity.)
  2. Adăugați o instrucțiune de jurnal la metoda returnReply() chiar înainte de metoda finish():
Log.d(LOG_TAG, "End SecondActivity");

1.4 Observați jurnalul în timp ce aplicația rulează**

  1. Rulați aplicația.
  2. Faceți clic pe fila Logcat din partea de jos a Android Studio pentru a afișa panoul Logcat.
  3. Introduceți Activitate în caseta de căutare. Logcat-ul Android poate fi foarte lung și aglomerat. Deoarece variabila LOG_TAG din fiecare clasă conține fie cuvintele MainActivity, fie SecondActivity, acest cuvânt cheie vă permite să filtrați jurnalul numai pentru lucrurile care vă interesează.

dublu necaz

Experimentați folosind aplicația dvs. și rețineți că evenimentele ciclului de viață care apar ca răspuns la diferite acțiuni. În special, încercați aceste lucruri:

  • Utilizați aplicația în mod normal (trimiteți un mesaj, răspundeți cu un alt mesaj).
  • Utilizați butonul Înapoi pentru a reveni de la a doua activitate la activitatea principală.
  • Utilizați săgeata în sus din bara de aplicații pentru a reveni de la a doua activitate la activitatea principală.
  • Rotiți dispozitivul atât pe activitatea principală, cât și pe cea de-a doua, în momente diferite din aplicația dvs. și observați ce se întâmplă în * jurnal și pe ecran.
  • Apăsați butonul de prezentare generală (butonul pătrat din dreapta Home) și închideți aplicația (atingeți X).
  • Reveniți la ecranul de pornire și reporniți aplicația.

SFAT: dacă rulați aplicația într-un emulator, puteți simula rotația cu Control+F11 sau Control+Function+F11.

Codul soluției pentru sarcina 1

Următoarele fragmente de cod arată codul soluției pentru prima sarcină.

Activitatea principală

Următoarele fragmente de cod arată codul adăugat în MainActivity, dar nu întreaga clasă.

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

Celelalte metode de ciclu de viață:

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

A doua activitate

Următoarele fragmente de cod arată codul adăugat în SecondActivity, dar nu întreaga clasă.

În partea de sus a clasei 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();
}

Celelalte metode de ciclu de viață:

La fel ca pentru MainActivity, mai sus.

4. 4. Sarcina 2: Salvați și restaurați starea instanței de activitate

În funcție de resursele sistemului și de comportamentul utilizatorului, fiecare activitate din aplicația dvs. poate fi distrusă și reconstruită mult mai des decât ați crede.

Este posibil să fi observat acest comportament în ultima secțiune când ați rotit dispozitivul sau emulatorul. Rotirea dispozitivului este un exemplu de modificare a configurației dispozitivului. Deși rotația este cea mai comună, toate modificările de configurare au ca rezultat distrugerea și recrearea activității curente ca și cum ar fi nouă. Dacă nu țineți cont de acest comportament în codul dvs., atunci când are loc o modificare a configurației, aspectul activității dvs. poate reveni la aspectul implicit și la valorile inițiale, iar utilizatorii dvs. își pot pierde locul, datele sau starea progresului lor în aplicația dvs.

Starea fiecărei activități este stocată ca un set de perechi cheie/valoare într-un obiect Bundle numit starea instanței Activitate. Sistemul salvează informații despre starea implicită în pachetul de stare a instanței chiar înainte ca Activitatea să fie oprită și transmite acel pachet la noua instanță de activitate pentru a fi restaurat.

Pentru a evita pierderea datelor dintr-o Activitate atunci când aceasta este distrusă și recreată în mod neașteptat, trebuie să implementați metoda onSaveInstanceState(). Sistemul apelează această metodă în activitatea dvs. (între onPause() și onStop()) atunci când există posibilitatea ca Activitatea să fie distrusă și recreată.

Datele pe care le salvați în starea instanței sunt specifice numai acestei instanțe a acestei activități specifice în timpul sesiunii curente a aplicației. Când opriți și reporniți o nouă sesiune de aplicație, starea instanței de activitate se pierde și activitatea revine la aspectul implicit. Dacă trebuie să salvați datele utilizatorului între sesiunile de aplicație, utilizați preferințe partajate sau o bază de date. Veți afla despre ambele acestea într-o practică ulterioară.

2.1 Salvați starea instanței de activitate cu onSaveInstanceState()

Este posibil să fi observat că rotirea dispozitivului nu afectează deloc starea celei de-a doua activități. Acest lucru se datorează faptului că al doilea aspect și stare de activitate sunt generate din aspect și intenția care a activat-o. Chiar dacă Activitatea este recreată, Intenția este încă acolo și datele din acea Intenție sunt încă folosite de fiecare dată când este apelată metoda onCreate() din a doua Activitate.

În plus, este posibil să observați că, în fiecare activitate, orice text pe care l-ați introdus în elementele de mesaj sau răspuns EditText este reținut chiar și atunci când dispozitivul este rotit. Acest lucru se datorează faptului că informațiile despre starea unora dintre elementele View din aspectul dvs. sunt salvate automat în timpul modificărilor de configurare, iar valoarea curentă a unui EditText este unul dintre aceste cazuri.

Deci, singura stare de activitate care vă interesează sunt elementele TextView pentru antetul de răspuns și textul de răspuns din Activitatea principală. Ambele elemente TextView sunt invizibile implicit; ele apar numai după ce trimiteți un mesaj înapoi la Activitatea principală din a doua Activitate.

În această sarcină adăugați cod pentru a păstra starea instanței acestor două elemente TextView folosind onSaveInstanceState().

  1. Deschide MainActivity.
  2. Adăugați această implementare schelet a onSaveInstanceState() la activitate sau utilizați Code > Override Methods pentru a insera o schelet override.
@Override
public void onSaveInstanceState(Bundle outState) {
          super.onSaveInstanceState(outState);
}
  1. Verificați dacă antetul este vizibil în prezent și, dacă da, puneți acea stare de vizibilitate în starea Bundle cu metoda putBoolean() și cheia „reply_visible”.
 if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
        outState.putBoolean("reply_visible", true);
    }

Rețineți că antetul de răspuns și textul sunt marcate invizibile până când există un răspuns de la a doua activitate. Dacă antetul este vizibil, atunci există date de răspuns care trebuie salvate. Rețineți că ne interesează doar acea stare de vizibilitate - textul real al antetului nu trebuie să fie salvat, deoarece acel text nu se schimbă niciodată.

  1. În cadrul aceleiași verificări, adăugați textul de răspuns în pachet.
outState.putString("reply_text",mReplyTextView.getText().toString());

Dacă antetul este vizibil, puteți presupune că mesajul de răspuns în sine este și el vizibil. Nu trebuie să testați sau să salvați starea curentă de vizibilitate a mesajului de răspuns. Doar textul real al mesajului intră în pachetul de stare cu cheia „reply_text”.

Salvați starea doar a acelor elemente de vizualizare care s-ar putea modifica după crearea activității. Celelalte elemente View din aplicația dvs. (EditText, Button) pot fi recreate din aspectul implicit în orice moment.

Rețineți că sistemul va salva starea unor elemente View, cum ar fi conținutul EditText.

2.2 Restaurați starea instanței de activitate în onCreate()

După ce ați salvat starea instanței de activitate, trebuie să o restabiliți și atunci când activitatea este recreată. Puteți face acest lucru fie în onCreate(), fie prin implementarea apelului onRestoreInstanceState(), care este apelat după onStart() după crearea activității.

De cele mai multe ori, locul mai bun pentru a restabili starea Activitate este în onCreate(), pentru a vă asigura că interfața de utilizare, inclusiv starea, este disponibilă cât mai curând posibil. Uneori este convenabil să o faceți în onRestoreInstanceState() după ce toată inițializarea a fost făcută sau să permiteți subclaselor să decidă dacă să utilizeze implementarea implicită.

  1. În metoda onCreate(), după ce variabilele View sunt inițializate cu findViewById(), adăugați un test pentru a vă asigura că savedInstanceState nu este nul.
// 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) {
}

Când activitatea dvs. este creată, sistemul transmite pachetul de stare la onCreate() ca singur argument. Prima dată când onCreate() este apelat și aplicația dvs. pornește, pachetul este nul - nu există nicio stare existentă la prima pornire a aplicației. Apelurile ulterioare la onCreate() au un pachet populat cu datele pe care le-ați stocat în onSaveInstanceState().

  1. În cadrul acelei verificări, scoateți vizibilitatea curentă (adevărată sau falsă) din pachet cu cheia „reply_visible”.
if (savedInstanceState != null) {
    boolean isVisible = 
                     savedInstanceState.getBoolean("reply_visible");
}
  1. Adăugați un test sub acea linie anterioară pentru variabila isVisible.
if (isVisible) {
}

Dacă există o cheie reply_visible în pachetul de stare (și, prin urmare, isVisible este adevărat), va trebui să restabiliți starea.

  1. În interiorul testului isVisible, faceți antetul vizibil.
mReplyHeadTextView.setVisibility(View.VISIBLE);
  1. Obțineți mesajul de răspuns text de la pachet cu cheia „reply_text” și setați răspunsul TextView pentru a afișa acel șir.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
  1. Faceți și răspunsul TextView vizibil:
mReplyTextView.setVisibility(View.VISIBLE);
  1. Rulați aplicația. Încercați să rotiți dispozitivul sau emulatorul pentru a vă asigura că mesajul de răspuns (dacă există unul) rămâne pe ecran după recrearea activității.

Codul soluției pentru sarcina 2

Următoarele fragmente de cod arată codul soluției pentru această sarcină.

Activitatea principală

Următoarele fragmente de cod arată codul adăugat în MainActivity, dar nu întreaga clasă.

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

Proiectul complet:

Proiect Android Studio: TwoActivitiesLifecycle

5. Codificare

Provocare: creați o aplicație simplă pentru lista de cumpărături cu o activitate principală pentru lista pe care o creează utilizatorul și o a doua activitate pentru o listă de articole comune de cumpărături.

  • Activitatea principală ar trebui să conțină lista de construit, care ar trebui să fie alcătuită din zece elemente TextView goale.
  • Un buton Adăugare articol de pe activitatea principală lansează o a doua activitate care conține o listă de articole comune de cumpărături (brânză, orez, mere și așa mai departe). Utilizați elemente Button pentru a afișa elementele.
  • Alegerea unui articol returnează utilizatorul la activitatea principală și actualizează un textView Gol pentru a include elementul ales.

Utilizați o intenție de a trece informații de la o activitate la alta. Asigurați -vă că starea actuală a listei de cumpărături este salvată atunci când utilizatorul rotește dispozitivul.

6. Rezumat

  • Ciclul de viață al activității este un set de state pe care o activitate migrează, începând când este creată pentru prima dată și se termină atunci când sistemul Android recuperează resursele pentru acea activitate.
  • Pe măsură ce utilizatorul navighează de la o activitate la alta, și în interiorul și în afara aplicației dvs., fiecare activitate se deplasează între state în ciclul de viață al activității.
  • Fiecare stat din ciclul de viață al activității are o metodă de apel corespunzătoare pe care o puteți înlocui în clasa dvs. de activități.
  • Metodele ciclului de viață sunt onCreate (), onStart (), onPause (), onRestart (), onResume (), OnStop (), OnDestroy ().
  • Supravegherea unei metode de apel de apelare a ciclului de viață vă permite să adăugați un comportament care apare atunci când activitatea dvs. trece în această stare.
  • Puteți adăuga metode de înlocuire a scheletului la clasele dvs. în Android Studio cu cod> înlocuire.
  • Modificări de configurare a dispozitivului, cum ar fi rotirea rezultă ca activitatea să fie distrusă și recreată ca și cum ar fi nouă.
  • O parte din starea de activitate este păstrată pe o modificare a configurației, inclusiv valorile curente ale elementelor editText. Pentru toate celelalte date, trebuie să salvați în mod explicit aceste date.
  • Salvați starea de instanță de activitate în metoda ONSAVEINSTANCESTATE ().
  • Datele de stare de instanță sunt stocate sub formă de perechi simple de cheie/valoare într -un pachet. Utilizați metodele de pachet pentru a introduce datele și pentru a obține datele din pachet.
  • Restaurați starea de instanță în onCreate (), care este modul preferat, sau onRestoreInstanceState (). Spate
,

1. Bun venit

Acest codelab practic face parte din unitatea 1: Începeți în cursul Fundamentelor Android Developer Fundamentals (Versiunea 2). Veți obține cea mai mare valoare din acest curs dacă lucrați prin Codelabs în secvență:

  • Pentru lista completă a codelabilor din curs, consultați Codelabs pentru Android Developer Fundamentals (V2).
  • Pentru detalii despre curs, inclusiv link -uri către toate capitolele conceptuale, aplicații și diapozitive, consultați Android Developer Fundamentals (versiunea 2).

Introducere

În acest lucru, aflați mai multe despre ciclul de viață al activității. Ciclul de viață este setul de state, o activitate poate fi pe parcursul întregii sale vieți, de când este creat până când este distrus și sistemul își recuperează resursele. Pe măsură ce un utilizator navighează între activitățile din aplicația dvs. (precum și în aplicația dvs. și din aplicația dvs.), activitățile se tranziționează între diferite state în ciclurile lor de viață.

Probleme Idouble

Fiecare etapă din ciclul de viață al unei activități are o metodă de apel corespunzătoare: onCreate (), onStart (), onPause () și așa mai departe. Când o activitate se schimbă stabilește, metoda de apel asociată este invocată. Ați văzut deja una dintre aceste metode: onCreate (). Prin depășirea oricăreia dintre metodele de apel de apel de ciclu de viață din clasele dvs. de activitate, puteți modifica comportamentul implicit al activității ca răspuns la acțiunile utilizatorului sau sistemului.

Starea de activitate se poate schimba, de asemenea, ca răspuns la modificările de configurare a dispozitivului, de exemplu atunci când utilizatorul rotește dispozitivul de la portret la peisaj. Când aceste modificări de configurare se întâmplă, activitatea este distrusă și recreată în starea sa implicită, iar utilizatorul ar putea pierde informații pe care le -au introdus în activitate. Pentru a evita confundarea utilizatorilor dvs., este important să vă dezvoltați aplicația pentru a preveni pierderea neașteptată a datelor. Mai târziu, în acest lucru, experimentați cu modificări de configurare și învățați cum să păstrați starea unei activități ca răspuns la modificările de configurare a dispozitivului și la alte evenimente de ciclu de viață a activității.

În acest lucru, adăugați declarații de logare la aplicația TwoActive și observați modificările ciclului de viață ale activității în timp ce utilizați aplicația. Apoi începeți să lucrați cu aceste modificări și să explorați modul de gestionare a introducerii utilizatorului în aceste condiții.

Cerințe preliminare

Ar trebui să poți:

  • Creați și executați un proiect de aplicație în Android Studio .
  • Adăugați declarații de jurnal la aplicația dvs. și vizualizați acele jurnale în panoul LogCat.
  • Înțelegeți și lucrați cu o activitate și o intenție și fiți confortabil interacționând cu ei.

Ce vei învăța

  • Cum funcționează ciclul de viață al activității.
  • Când începe o activitate, se oprește, se oprește și este distrusă.
  • Despre metodele de apelare a ciclului de viață asociate cu schimbările de activitate.
  • Efectul acțiunilor (cum ar fi modificările de configurare) care pot duce la evenimente de ciclu de viață a activității.
  • Cum se păstrează starea de activitate în evenimentele ciclului de viață.

Ce vei face

  • Adăugați cod la aplicația TwoActivity din Practica anterioară pentru a implementa diferitele apeluri de cicl de viață pentru a include declarații de înregistrare.
  • Observați schimbările de stare pe măsură ce aplicația dvs. rulează și pe măsură ce interacționați cu fiecare activitate din aplicația dvs.
  • Modificați aplicația dvs. pentru a păstra starea de instanță a unei activități care este recreată pe neașteptate ca răspuns la comportamentul utilizatorului sau la modificarea configurației pe dispozitiv.

2. Prezentare generală a aplicației

În acest lucru, adăugați la aplicația TwoActivity . Aplicația arată și se comportă aproximativ la fel ca în ultimul codelb. Conține două implementări de activitate și oferă utilizatorului posibilitatea de a trimite între ele. Modificările pe care le faceți în aplicație în acest practic nu vor afecta comportamentul său vizibil al utilizatorului.

3. 3. Sarcina 1: Adăugați apeluri de ciclu de viață la două activități

În această sarcină veți implementa toate metodele de apel de apel de ciclu de viață pentru a imprima mesaje pentru a se înregistra atunci când aceste metode sunt invocate. Aceste mesaje de jurnal vă vor permite să vedeți când se schimbă ciclul de viață al activității și modul în care aceste modificări ale stării ciclului de viață afectează aplicația dvs. pe măsură ce rulează.

1.1 (opțional) Copiați proiectul TwoActivities

Pentru sarcinile din acest lucru practic, veți modifica proiectul de două activități existent pe care l -ați construit în ultimul practic. Dacă preferați să mențineți intact proiectul anterior al activităților, urmați pașii în apendice: utilități pentru a face o copie a proiectului.

1.2 Implementați apeluri în relativă în MainActivity

  1. Deschideți proiectul TwoActivity în Android Studio și deschideți MainActivity în Proiect> Android Pano.
  2. În metoda onCreate (), adăugați următoarele afirmații de jurnal:
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
  1. Adăugați o înlocuire pentru callback -ul onstart (), cu o declarație în jurnal pentru acel eveniment:
@Override
public void onStart(){
    super.onStart();
    Log.d(LOG_TAG, "onStart");
}

Pentru o comandă rapidă, selectați Cod> Onulare Metode în Android Studio. Apare un dialog cu toate metodele posibile pe care le puteți înlocui în clasa dvs. Alegerea uneia sau mai multor metode de apel de apel din listă introduce un șablon complet pentru aceste metode, inclusiv apelul necesar către superclasa.

  1. Utilizați metoda OnStart () ca șablon pentru a implementa onPause (), OnRestart (), OnResume (), OnStop () și OnDestroy () callback -uri de ciclu de viață

Toate metodele de apelare au aceleași semnături (cu excepția numelui). Dacă copiați și lipiți OnStart () pentru a crea aceste alte metode de apel de apel, nu uitați să actualizați conținutul pentru a apela metoda potrivită în superclasa și pentru a înregistra metoda corectă.

  1. Rulează aplicația ta.
  2. Faceți clic pe fila Logcat din partea de jos a Android Studio pentru a afișa panoul Logcat. Ar trebui să vedeți trei mesaje de jurnal care arată cele trei state ale ciclului de viață pe care activitatea le -a trecut pe măsură ce a început:
D/MainActivity: -------
D/MainActivity: onCreate
D/MainActivity: onStart
D/MainActivity: onResume

1.3 Implementați apeluri de ciclu de viață în SecondActivity

Acum, după ce ați implementat metodele de apel al ciclului de viață pentru MainActivity, faceți același lucru pentru SecondActivity.

  1. Deschideți a douaactivitate.
  2. În partea de sus a clasei, adăugați o constantă pentru variabila log_tag:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
  1. Adăugați apelurile de ciclu de viață și declarațiile de jurnal la a doua activitate. (Puteți copia și lipi metodele de apel de la MainActivity.)
  2. Adăugați o declarație de jurnal la metoda returnReply () chiar înainte de metoda Finish ():
Log.d(LOG_TAG, "End SecondActivity");

1.4 Observați jurnalul pe măsură ce aplicația rulează **

  1. Rulează aplicația ta.
  2. Faceți clic pe fila Logcat din partea de jos a Android Studio pentru a afișa panoul Logcat.
  3. Introduceți activitate în caseta de căutare. Logcatul Android poate fi foarte lung și aglomerat. Deoarece variabila log_tag din fiecare clasă conține fie cuvintele mainActivity, fie SecondActivity, acest cuvânt cheie vă permite să filtrați jurnalul doar pentru lucrurile care vă interesează.

Probleme Idouble

Experimentați folosind aplicația dvs. și rețineți că evenimentele ciclului de viață care apar ca răspuns la diferite acțiuni. În special, încercați aceste lucruri:

  • Utilizați aplicația în mod normal (trimiteți un mesaj, răspundeți cu un alt mesaj).
  • Utilizați butonul înapoi pentru a vă întoarce de la a doua activitate la activitatea principală.
  • Utilizați săgeata sus în bara de aplicații pentru a vă întoarce de la a doua activitate la activitatea principală.
  • Rotiți dispozitivul atât pe principalul, cât și pe cea de -a doua activitate în momente diferite în aplicația dvs. și observați ce se întâmplă în * jurnalul și pe ecran.
  • Apăsați butonul Prezentare generală (butonul pătrat din dreapta acasă) și închideți aplicația (atingeți X).
  • Reveniți la ecranul de pornire și reporniți aplicația.

Sfat: Dacă rulați aplicația într -un emulator, puteți simula rotația cu Control+F11 sau Control+Funcție+F11.

Sarcina 1 Cod de soluție

Următoarele fragmente de cod arată codul soluției pentru prima sarcină.

MainActivity

Următoarele fragmente de cod arată codul adăugat în MainActivity, dar nu întreaga clasă.

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

Celelalte metode ale ciclului de viață:

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

SecondActivitate

Următoarele fragmente de cod arată codul adăugat în SecondActivity, dar nu întreaga clasă.

În partea de sus a clasei 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();
}

Celelalte metode ale ciclului de viață:

La fel ca pentru MainActivity, de mai sus.

4. 4. Sarcina 2: Salvați și restaurați starea instanței de activitate

În funcție de resursele sistemului și de comportamentul utilizatorului, fiecare activitate din aplicația dvs. poate fi distrusă și reconstruită mult mai frecvent decât ați putea crede.

Este posibil să fi observat acest comportament în ultima secțiune când ați rotit dispozitivul sau emulatorul. Rotirea dispozitivului este un exemplu de modificare a configurației dispozitivului. Deși rotația este cea mai frecventă, toate modificările de configurare au ca rezultat distribuirea și recrearea activității curente ca și cum ar fi nouă. Dacă nu țineți cont de acest comportament în codul dvs., atunci când are loc o modificare a configurației, aspectul activității dvs. poate reveni la aspectul implicit și la valorile inițiale, iar utilizatorii dvs. își pot pierde locul, datele lor sau starea progresului lor în Aplicația dvs.

Starea fiecărei activități este stocată ca un set de perechi cheie/valori într -un obiect de pachet numit starea instanței de activitate. Sistemul salvează informații implicite de stare către Bundle de stat de instanță chiar înainte de oprirea activității și trece acel pachet către noua instanță de activitate pentru a restabili.

Pentru a nu pierde datele într -o activitate atunci când acestea sunt distruse și recreate neașteptat, trebuie să implementați metoda ONSAVEINSTANCESTATE (). Sistemul apelează această metodă pe activitatea dvs. (între onPause () și OnStop ()) Când există o posibilitate, activitatea poate fi distrusă și recreată.

Datele pe care le salvați în starea de instanță sunt specifice numai pentru această instanță a acestei activități specifice în timpul sesiunii de aplicație curentă. Când opriți și reporniți o nouă sesiune de aplicații, starea de instanță de activitate este pierdută și activitatea revine la aspectul implicit. Dacă trebuie să salvați datele utilizatorului între sesiunile de aplicații, utilizați preferințe partajate sau o bază de date. Aflați despre ambele acestea într -un practic mai târziu.

2.1 Salvați starea de instanță de activitate cu ONSAVEINSTANCESTATE ()

Este posibil să fi observat că rotirea dispozitivului nu afectează deloc starea celei de -a doua activități. Acest lucru se datorează faptului că al doilea aspect și starea activității sunt generate din aspectul și intenția care a activat -o. Chiar dacă activitatea este recreată, intenția este încă acolo și datele din această intenție sunt încă utilizate de fiecare dată când se numește metoda onCreate () în a doua activitate.

În plus, puteți observa că în fiecare activitate, orice text pe care l -ați tastat în mesaj sau răspuns la elemente editxt este păstrat chiar și atunci când dispozitivul este rotit. Acest lucru se datorează faptului că informațiile de stare ale unora dintre elementele de vizualizare din aspectul dvs. sunt salvate automat în cadrul modificărilor de configurare, iar valoarea curentă a unui ediText este unul dintre aceste cazuri.

Așadar, singura stare de activitate de care vă interesează sunt elementele TextView pentru antetul răspunsului și textul de răspuns în activitatea principală. Ambele elemente TextView sunt invizibile în mod implicit; Ele apar doar după ce trimiteți un mesaj înapoi la activitatea principală din a doua activitate.

În această sarcină adăugați cod pentru a păstra starea de instanță a acestor două elemente de text de text folosind onsaveinstancestate ().

  1. Deschideți MainActivity.
  2. Adăugați această implementare a scheletului de ONSAVEINSTANCESTATE () la activitate sau utilizați cod> Metode de înlocuire pentru a insera o înlocuire a scheletului.
@Override
public void onSaveInstanceState(Bundle outState) {
          super.onSaveInstanceState(outState);
}
  1. Verificați dacă antetul este în prezent vizibil și, dacă este așa, puneți acea stare de vizibilitate în pachetul de stat cu metoda Putboolean () și cheia „Răspuns_visible”.
 if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
        outState.putBoolean("reply_visible", true);
    }

Nu uitați că antetul și textul de răspuns sunt marcate invizibile până când există un răspuns din a doua activitate. Dacă antetul este vizibil, atunci există date de răspuns care trebuie salvate. Rețineți că ne interesează doar acea stare de vizibilitate - textul real al antetului nu trebuie salvat, deoarece acest text nu se schimbă niciodată.

  1. În aceeași verificare, adăugați textul de răspuns în pachet.
outState.putString("reply_text",mReplyTextView.getText().toString());

Dacă antetul este vizibil, puteți presupune că mesajul de răspuns în sine este de asemenea vizibil. Nu trebuie să testați sau să salvați starea de vizibilitate curentă a mesajului de răspuns. Doar textul propriu al mesajului intră în pachetul de stat cu cheia „Răspunde_text”.

Salvați starea numai a acestor elemente de vedere care s -ar putea schimba după crearea activității. Celelalte elemente de vizualizare din aplicația dvs. (editText, butonul) pot fi recreate din aspectul implicit în orice moment.

Rețineți că sistemul va salva starea unor elemente de vizualizare, cum ar fi conținutul EditText.

2.2 Restaurați starea instanței de activitate în onCreate ()

După ce ați salvat starea de instanță de activitate, trebuie să o restaurați și atunci când activitatea este recreată. Puteți face acest lucru fie în OnCreate (), fie prin implementarea apelului de apel OnRestoreInstanceState (), care se numește după OnStart () după crearea activității.

De cele mai multe ori, locul mai bun pentru a restabili starea de activitate este în OnCreate (), pentru a se asigura că UI, inclusiv statul, este disponibil cât mai curând posibil. Uneori este convenabil să o faci în OnReStoreInsceState () după ce a fost făcută toată inițializarea sau pentru a permite subclaselor să decidă dacă să folosești implementarea implicită.

  1. În metoda onCreate (), după ce variabilele de vizualizare sunt inițializate cu FindViewById (), adăugați un test pentru a vă asigura că SaveDInsTanceState nu este nulă.
// 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) {
}

Când activitatea dvs. este creată, sistemul trece pachetul de stat la onCreate () ca singurul său argument. Prima dată când se numește onCreate () și începe aplicația dvs., pachetul este nul - nu există o stare existentă pentru prima dată când începe aplicația dvs. Apelurile ulterioare către onCreate () au un pachet populat cu datele pe care le -ați stocat în OnSaveInsceState ().

  1. În interiorul acestei verificări, scoateți vizibilitatea curentă (adevărată sau falsă) din pachet cu cheia „Răspuns_visible”.
if (savedInstanceState != null) {
    boolean isVisible = 
                     savedInstanceState.getBoolean("reply_visible");
}
  1. Adăugați un test mai jos acea linie anterioară pentru variabila ISVISIBLE.
if (isVisible) {
}

Dacă există o cheie de răspuns_visibile în pachetul de stat (și este, prin urmare, este adevărat), va trebui să restabiliți statul.

  1. În interiorul testului isvisibil, faceți antetul vizibil.
mReplyHeadTextView.setVisibility(View.VISIBLE);
  1. Obțineți mesajul de răspuns text din pachet cu cheia „Răspunde_text” și setați răspunsul TextView pentru a afișa șirul respectiv.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
  1. Faceți vizibil răspunsul la răspuns:
mReplyTextView.setVisibility(View.VISIBLE);
  1. Rulați aplicația. Încercați să rotiți dispozitivul sau emulatorul pentru a vă asigura că mesajul de răspuns (dacă există unul) rămâne pe ecran după recrearea activității.

Sarcina 2 Cod de soluție

Următoarele fragmente de cod arată codul soluției pentru această sarcină.

MainActivity

Următoarele fragmente de cod arată codul adăugat în MainActivity, dar nu întreaga clasă.

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

Proiectul complet:

Proiect Android Studio: TwoActivitiesLifecycle

5. Codificare

Provocare: Creați o aplicație simplă de lista de cumpărături cu o activitate principală pentru lista pe care o construiește utilizatorul și o a doua activitate pentru o listă de articole de cumpărături comune.

  • Activitatea principală ar trebui să conțină lista de construit, care ar trebui să fie alcătuită din zece elemente goale de text.
  • Un buton Adăugare element din activitatea principală lansează o a doua activitate care conține o listă de articole de cumpărături comune (brânză, orez, mere și așa mai departe). Utilizați elemente de buton pentru a afișa elementele.
  • Alegerea unui articol returnează utilizatorul la activitatea principală și actualizează un textView Gol pentru a include elementul ales.

Utilizați o intenție de a trece informații de la o activitate la alta. Asigurați -vă că starea actuală a listei de cumpărături este salvată atunci când utilizatorul rotește dispozitivul.

6. Rezumat

  • Ciclul de viață al activității este un set de state pe care o activitate migrează, începând când este creată pentru prima dată și se termină atunci când sistemul Android recuperează resursele pentru acea activitate.
  • Pe măsură ce utilizatorul navighează de la o activitate la alta, și în interiorul și în afara aplicației dvs., fiecare activitate se deplasează între state în ciclul de viață al activității.
  • Fiecare stat din ciclul de viață al activității are o metodă de apel corespunzătoare pe care o puteți înlocui în clasa dvs. de activități.
  • Metodele ciclului de viață sunt onCreate (), onStart (), onPause (), onRestart (), onResume (), OnStop (), OnDestroy ().
  • Supravegherea unei metode de apel de apelare a ciclului de viață vă permite să adăugați un comportament care apare atunci când activitatea dvs. trece în această stare.
  • Puteți adăuga metode de înlocuire a scheletului la clasele dvs. în Android Studio cu cod> înlocuire.
  • Modificări de configurare a dispozitivului, cum ar fi rotirea rezultă ca activitatea să fie distrusă și recreată ca și cum ar fi nouă.
  • O parte din starea de activitate este păstrată pe o modificare a configurației, inclusiv valorile curente ale elementelor editText. Pentru toate celelalte date, trebuie să salvați în mod explicit aceste date.
  • Salvați starea de instanță de activitate în metoda ONSAVEINSTANCESTATE ().
  • Datele de stare de instanță sunt stocate sub formă de perechi simple de cheie/valoare într -un pachet. Utilizați metodele de pachet pentru a introduce datele și pentru a obține datele din pachet.
  • Restaurați starea de instanță în onCreate (), care este modul preferat, sau onRestoreInstanceState (). Spate