Sunteți pe pagina 1din 12

INTRO ANDROID STUDIO

ACTIVITĂȚI

In sistemul Android ferestrele se numesc activitati. Din punct de vedere al programarii,


acestea sunt clase care extind clasa Activity. Spre deosebire de alte sisteme in care un program
contine mai multe ferestre afisate simultan, in Android, ecranul este mereu ocupat de o singura
fereastra. Mai mult, ferestrele sunt conectate prin simplul fapt ca o fereastra da nastere mai
multor ferestre. Fereastra care apare pe ecran in momentul in care aplicatia este pornita este
considerata fereastra principala, din ea pornind toate celelalte. Pentru a crea o activitate, vom
crea o clasa ce extinde clasa Activity. La pornire, programul o va genera, iar noi putem
interactiona cu fereastra prin evenimente. Unele dintre cele mai importante evenimente sunt:
onCreate si onPause.

public class MainActivity extends Activity


{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onPause()
{
// TODO Auto-generated method stub
super.onPause();
}
}
Nu uitati sa apelati functia parintelui (in exemplul nostru Activity) in interiorul
evenimentelor!
ONCREATE

Evenimentul este apelat in momentul in care se creaza activitate. Aici vom initializa
compentele ferestrei. Pentru a face elementele de pe fereastra vizibile, este necesar sa apelam
functia setContentView. Exista cazuri in care la pornirea eplicatiei, aceasta trebuie sa revina la o
stare anterioara (ex: dupa o oprire fortata). Astfel, este recomandat ca in acest aveniment sa se
verifice daca fereastra este una noua sau nu, adica daca variabila de tip Bundle pasata ca
parametru este nula sau nu.

if (savedInstanceState!=null)
{
//fereastra nu e noua si trebuie incarcate anumite date ramase
}
else
{
//fereastra e noua
}

ONPAUSE

Cand acest eveniment este apelat, fereastra se pregateste pentru oprire. De aceea este
important sa salvam toate schimbarile de care avem nevoie. Aici vom opri procesele care nu mai
sunt necesare cand aplicatia nu ruleaza, cum ar fi elementele video sau audio.

GESTIUNEA STARII UNEI ACTIVITATI

Unele dintre metodele care gestionează ciclul de viață al unei activități primesc ca parametru
un obiect de tip Bundle (https://developer.android.com/reference/android/os/Bundle.html),
utilizat pentru gestiunea stării în cazul în care activitatea este distrusă din lipsă de memorie:

 onCreate() - parametrul savedInstance poate să fie null, daca 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 ascunsă și există
posibilitatea ca procesul acesteia să fie terminat din lipsă de memorie, pentru a salva
starea activității;
 onRestoreInstanceState() - este apelată doar dacă există o stare a activității care ar
trebui să fie restaurată.

Obiectul de tip Bundle este o formă de hash map, în care cheia este întotdeauna de tip String,
iar valorile au tipul android.os.Parcelable (asemănător cu Serializable din Java, deși acesta nu
este un mecanism de serializare în sine).

Starea unei activități este menținută atâta vreme cât ea este activă (deci inclusiv când au fost
apelate metodele onPause() și onStop()), aceasta putând fi restaurată corespunzător.
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 (se modifică orientarea dispozitivului de afișare -
portrait vs. landscape, limba, disponibilitatea tastaturii), întrucât de fiecare dată este necesar să
se (re)încarce resursele specifice pentru valorile respective.

Ținându-se cont de faptul că activitatea poate fi terminată/distrusă în orice moment după ce


nu se mai găsește în prim-plan / este ascunsă, asigurarea consistenței trebuie realizată de fiecare
dată.

SALVAREA STĂRII

Metoda onSaveInstanceState() este înainte de metoda onStop() și posibil înainte de


metoda onPause(), deși acest lucru nu este garantat. 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ă (utilizatorul a
terminat activitatea prin apăsarea butonului Back).

În cazul în care se dorește salvarea explicită a conținutului unui obiect EditText, se poate
proceda astfel:

@Override
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
EditText myEditText = (EditText)findViewById(R.id.my_edit_text);
savedInstanceState.putString("myEditText", myEditText.getText());
}
Valoarea introdusă de utilizator va fi salvată în obiectul de tip Bundle sub denumirea
userNameEditText, acesta fiind menținut și prin urmare utilizat între mai multe instanțe ale
acestei activități.

Apelarea metodei părinte este necesară întrucât API-ul Android furnizează o


implementare implicită pentru salvarea stării unei activități, parcurgând ierarhia de componente
grafice (obiecte de tip View) care au asociat un identificator (android:id), folosit drept cheie în
obiectul Bundle.

Astfel, de regulă, pentru elementele interfeței grafice, nu este necesar să se mențină


starea, acest lucru fiind realizat în mod automat, cu respectarea condiției menționate. 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 nu se
va realiza niciodată aici (întrucât nu se garantează apelarea sa), ci în metoda onPause().

În obiectul de tip Bundle, prin cheia android:viewHierarchyState se va reține un alt


obiect de tip Bundle care reține starea tuturor obiectelor de tip View din cadrul activității (care
sunt identificate prin intermediul unui câmp android:id).

În cadrul acestuia, prin cheia android:views se reține un obiect de tip SparseArray (un
tip de dată specific Android care realizează mapări între întregi și obiecte, mai eficient decât un
hashmap) care conține starea fiecărui obiect de tip View prin intermediul identificatorului său.

Bundle viewHierarchy = savedInstanceState.getBundle("android:viewHierarchyState");


if (viewHierarchy != null) {
SparseArray<? extends Parcelable> views =
viewHierarchy.getSparseParcelableArray("android:views");
for (int k=0; k < views.size(); k++) {
Log.d("BundleTAG", views.get(k) + "->" + views.valueAt(k));
}
}
else {
Log.d("BundleTAG", "No view information was saved!");
}

Prin urmare, dacă aplicația este oprită și apoi pornită din nou, obiectele de tip View vor
avea conținutul existent în prealabil. Pentru a dezactiva această opțiune, trebuie specificată în
fișierul .xml care descrie interfața grafică a activității, în elementul corespunzător obiectului de
tip View proprietatea android:saveEnabled=“false”.

Dezactivarea se poate realiza și programatic, folosind metoda setSaveEnabled


(boolean).
RESTAURAREA STĂRII

Încărcarea conținutului din obiectul de tip Bundle (în vederea restaurării stării) poate fi
realizată:

1. în metoda onCreate()

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lifecycle_monitor);
EditText usernameEditText = (EditText)findViewById(R.id.my_edit_text);
if ((savedInstanceState != null) && (savedInstanceState.getString("myEditText") != null)) {
usernameEditText.setText(savedInstanceState.getString("myEditText"));}}

2. 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

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
EditText usernameEditText= (EditText)findViewById(R.id.my_edit_text);
if (savedInstanceState.getString("myEditText") != null) {
usernameEditText.setText(savedInstanceState.getString(Constants.MY_EDIT_TEXT));
}}

TRANSMISIA DATELOR INTRE ACTIVITATI

De cele mai multe ori, la trecerea intre activitati vom vrea sa si pasam informatie. Desi
metodele sunt numeroase, pentru moment va vom arata pasarea de variabile prin Intentii
(https://developer.android.com/reference/android/content/Intent.html)
In activitatea din care se initiaza transferul trebuie definit un intent. In cadrul acestuia
putem adauga variabila dorita prin metoda putExtra. Aceasta poate aproape toate tipurile de
baza, dar si obiecte custom, atata timp cat acestea extind Parcelable sau Serializable.

public class MainActivity extends AppCompatActivity {


@Override
protected void onCreate(Bundle savedInstanceState) { ... }

@Override
public boolean onCreateOptionsMenu(Menu menu) { ... }

@Override
public boolean onOptionsItemSelected(MenuItem item) { ... }

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 {


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello);
TextView helloText = (TextView) findViewById(R.id.textView);
Bundle extras = getIntent().getExtras();
if (extras != null) {
String nume = extras.getString("Nume");
if (nume != null && nume.length() > 0) {
helloText.setText("Hello, " + nume);
} else {
helloText.setText("Hello there!");
}
} else {
helloText.setText("Hello there!");
}}}

DEPANARE

Depanarea este foarte importanta in procesul de realizare a aplicatiilor pentru dispozitive


mobile. Acest proces este insa putin diferit fata de depanarea programelor clasice pentru
calculator, in primul rand pentru ca ruleaza pe alt dispozitiv. Tocmai din acest motiv, avem
nevoie de programe spcializate pentru a realiza depanarea.

De asemenea, fiind vorba de dispozitive mobile, apar si anumite evenimente specifice, cum
ar fi apeluri telefonice, descarcarea bateriei etc., evenimente ce trebuie tratate intr-un fel sau
altul.

In laboratorul de astazi vom prezenta programele de depanare existente si modul lor de


functionare. De asemenea, ne vom ocupa putin de studierea evenimentelor ferestrelor.

1. Logcat - debugging monitor pentru Android. Apeland Log.d(“TAG”, “Text”) putem


afisa orice informatie ne putem dori. De asemenea, Log poate avea mai multe prioritati,
acestea determinand nivelul de importanta al mesajului si ajutand la filtrarea mai usoara
(In mesajele din logcat apar atat cele de la aplicatia in curs de rulare cat si alte mesaje
de log ale sistemului de operare si ale altor aplicatii care ruleaza in background).
o exemplu de utilizare a unui Log:

o rezultat (ultima linie):


2. DDMS - utilitarul pentru depanarea aplicatiilor pentru Android se numeste DDMS
(Dalvik Debug Monitor System). Acesta foloseste de fapt un alt utilitar, numit ADB
(Android Debug Bridge), pentru a se conecta la simulatoare sau dispozitive fizice. Cu
ajutorul DDMS putem vizualiza parametrii dispozitivului si a programelor ce ruleaza pe
acesta.
o pentru a rula pana la linia cu pricina, mai intai setam un breakpoint (click in
stanga liniei):

o apoi putem rula in debug mode:

o dupa care putem observa valoarea din variabila noastra:


o de asemenea putem adauga si in watch expresii mai complicate (try it out)

EXERCITII

1. Realizati o activitate careia ii suprascrieti urmatoarele functii de eveniment. Afisati cate


un mesaj de log in fiecare dintre aceste functii. Pentru a putea citi mai usor mesajele de
log afisate de catre programul vostru, o sa creati un filtru de log dupa tag-ul eveniment.

Log.d("AWESOME_TAG", "??? method was invoked");

o onCreate, onRestart , onStart, onResume, onPause, onStop, onDestroy;


2. Sa se modifice mesajul din metoda onCreate(), astfel incat sa se indice daca activitatea a
mai fost lansata in executie anterior sau nu (daca exista o stare a activitatii care trebuie
restaurata).
3. Observati ce se intampla cu evenimentele ferestrelor cand:
o Primiti un apel telefonic (Hint: utilizati Emulator Control din DDMS)
o Se apasa butonul Home
o Se tine mult apasat butonul Home
o Se apasa butonul de raspundere la convorbire
o Se apasa butonul de inchidere al ecranului (este butonul de inchidere a
convorbrii)
4. Adaugati pe fereastra un EditText si un CheckBox. Observati ce se intampla in cazurile
de mai sus.
5. Dezactivati optiunea de salvare a starii, dupa care repetati pasii din exercitiul anterior.
6. Salvati starea EditBox-ului si a CheckBox-ului in functia de salvare a starii (hint:
utilizati putString si putBoolean), fara a modifica functia onCreate si/sau
onRestoreInstanceState, observati ce se intampla in cazurile de mai sus.
7. Creati un Empty activity. In MainActivity (in content_main.xml mai exact) creati un
EditText in care sa faceti input pentru nume, urmat de un Buton. Nu va chinuiti sa-l
faceti sa arate bine sau ceva, importanta e functionalitatea. Adaugati logica butonului
astfel incat sa permita navigarea la activitatea noua, transmitand numele din EditText si
afisand textul “Hello, ” + numele transmis.

S-ar putea să vă placă și