Laborator Activities În sistemul Android activitățile reprezintă echivalentul ferestrelor din Windows, fiind clase care extind clasa Activity. Spre deosebire de alte sisteme, în Android ecranul este mereu ocupat de o singură fereastră (activitate). Fereastra care apare pe ecran în momentul în care aplicația este pornită este considerată fereastra principală, din ea pornind toate celelalte. Cu o fereastră se poate interacționa prin evenimente. Ciclul de viață pentru o activitate este reprezentat în diagrama de mai jos: Activity life cycle diagram (sursa: android.com) oncreate() Evenimentul se declanșează când activitatea este creată pentru prima dată. Aici se vor inițializa componentele ferestrei. Elementele de pe interfață se fac vizibile apelând setcontentview. Există cazuri în care la pornirea eplicației, aceasta trebuie să revină la o stare anterioară (ex: dupa o oprire forțată). Astfel, se poate verifica dacă fereastra este una nouă sau nu testând dacă variabila de tip Bundle primită ca parametru este nula sau nu. 1 M. Apetrii
if (savedinstancestate!=null) //fereastra nu este noua si trebuie incarcate anumite date ramase else //fereastra este noua onstart() Evenimentul se declanșează când activitatea devine vizibilă utilizatorului. onresume() Evenimentul se declanșează atunci când utilizatorul începe să interacționeze cu aplicația. onpause() Evenimentul se declanșează atunci când activitatea se pregătește să se oprească. Aici se vor salva informațiile de care este nevoie, se vor opri procesele care nu mai sunt necesare când aplicația nu rulează (ex.: elementele video sau audio). onstop() Evenimentul se declanșează atunci când activitatea nu mai este vizibilă. ondestroy() Evenimentul se declanșează înainte ca activitatea să fie distrusă de sistem. onrestart() Evenimentul se declanșează atunci când activitatea repornește după pornirea acesteia. Gestiunea Starii unei Activitati Unele dintre metodele care gestionează ciclul de viață al unei activități primesc ca parametru un obiect de tip Bundle, utilizat pentru gestiunea stării în cazul în care activitatea este distrusă din lipsă de memorie: oncreate() - parametrul savedinstance poate să fie null, dacă activitatea nu a mai fost rulată anterior, fie este o instanță a unui obiect de tip Bundle în care se găsește starea anterioară (așa cum a fost reținută de metoda onsaveinstancestate()); onsaveinstancestate() - este apelată când activitatea urmează să fie oprita, pentru a salva starea activității; onrestoreinstancestate() - este apelată doar dacă există o stare a activității care ar trebui să fie restaurată. 2 M. Apetrii
(sursa: android.com) Obiectul de tip Bundle este o formă de hash map, în care cheia este întotdeauna de tip String. Starea unei activități este menținută atâta vreme cât ea este activă (chiar dacă au fost apelate metodele onpause() și onstop()). Necesitatea asigurării consistenței activității de către programator apare în momentul în care activitatea este terminată/distrusă și apoi (re)pornită. O astfel de situație este frecventă în cazul în care se produce o schimbare de configurație (ex.: se modifică orientarea dispozitivului) Salvarea Stării Metoda onsaveinstancestate() se apelează înainte de metoda onstop(). Ea primește ca parametru un obiect de tip Bundle în care vor fi plasate datele din cadrul activității care se doresc a fi salvate, acestea putând fi identificate prin intermediul unei chei (de tip String). Apelul metodei onsaveinstancestate() nu este garantat să fie realizat de fiecare dată întrucât pot fi situații în care nu este necesar ca starea activității să fie restaurată (ex.:utilizatorul a terminat activitatea prin apăsarea butonului Back). Exemplu: protected void onsaveinstancestate(bundle savedinstancestate)... savedinstancestate.putstring("username", useredittext.gettext()); De regulă, pentru elementele interfeței grafice, nu este necesar să se mențină starea, acest lucru fiind realizat în mod automat (dacă se rescrie metoda parinte). De aceea, în metoda onsaveinstancestate, va fi realizată salvarea unor informații (obiecte ale clasei) pentru care procesul de salvare a stării nu este apelat. Totuși, asigurarea persistenței datelor se va realiza în metoda onpause()întrucât se garantează apelarea sa, pentru onsaveinstancestate() având garanția că se apelează înainte de metoda onstop(). 3 M. Apetrii
Restaurarea Stării Încărcarea conținutului din obiectul de tip Bundle (în vederea restaurării stării) poate fi realizată: în metoda oncreate() protected void oncreate(bundle savedinstancestate)... EditText useredittext = (EditText)findViewById(R.id.user_edit_text); if ((savedinstancestate!= null) && (savedinstancestate.getstring("username")!= null)) useredittext.settext(savedinstancestate.getstring("username")); prin intermediul metodei onrestoreinstancestate(), apelată în mod automat între metodele onstart() și onresume(); această abordare permite separarea dintre codul folosit la crearea ferestrei și codul utilizat la restaurarea stării unei ferestre. Transmisia datelor între activități Există numeroase variate de transmitere a informațiilor de la o activitate la alta, însă cea mai des folosită este transmiterea de variabile prin Intenții. În activitatea din care se inițiază transferul trebuie definit un intent, în cadrul acestuia putând adăuga variabilele dorite prin metoda putextra. Aceasta primește tipuri de bază, dar și obiecte custom dacă acestea extind Parcelable sau Serializable. public class MainActivity extends AppCompatActivity protected void oncreate(bundle savedinstancestate)... public void oncenterbuttonclick(view view) EditText inputname = (EditText) findviewbyid(r.id.edittext); Intent intent = new Intent(getApplicationContext(), HelloActivity.class); intent.putextra("nume", inputname.gettext().tostring()); startactivity(intent); In noua activitate, extragem datele trimise prin intent astfel: public class HelloActivity extends AppCompatActivity protected void oncreate(bundle savedinstancestate) super.oncreate(savedinstancestate); setcontentview(r.layout.activity_hello); TextView campmesaj = (TextView) findviewbyid(r.id.textview); 4 M. Apetrii
Bundle extras = getintent().getextras(); if (extras!= null) String nume = extras.getstring("nume"); if (nume!= null && nume.length() > 0) campmesaj.settext("salut, " + nume); else campmesaj.settext("salut!"); else campmesaj.settext("salut!"); Pentru un exemplu click aici. 1. Să se realizeze o aplicație în care să se suprascrie urmatoarele funcții de eveniment: oncreate, onrestart, onstart, onresume, onpause, onstop, ondestroy. Se vor afișa mesaje de log de forma: Log.d("TAG_EVENIMENT", "A fost invocata metoda -..."); 2. Să se modifice mesajul din metoda oncreate() astfel încât să se indice dacă activitatea a mai fost lansată în execuție anterior sau nu. 3. Să se observe ce se întâmplă cu evenimentele ferestrelor când: o se primește un apel telefonic o se apasă butonul Home o se ține mult apăsat butonul Home o se apasă butonul de răspundere la convorbire o se apasă butonul de închidere al ecranului 4. Să se adauge un EditText și un CheckBox apoi să se observe ce se întamplă în cazurile de mai sus (inclusiv cu opțiunea de dezactivare pentru salvarea stării, sau cu salvarea stării utilizând putstring și putboolean, fără a modifica funcția oncreate și/sau onrestoreinstancestate). 5. Să se creeze o aplicație în care făcând click pe un buton, numele trecut într-un EditText să fie transmis la o nouă activitate în care se va afișa textul Salut, + numele transmis. 5 M. Apetrii