Un'activity, dunque, descrive attraverso una schermata una possibile interazione per l'utente. Poiché in Android il focus spetta a una sola activity, il sistema operativo attribuisce alle attività diversi stati. Ognuno di questi contribuisce allora alla definizione di un ciclo di vita per le applicazioni. L'applicazione, quindi l'activity che la rappresenta in quel momento, viene condotta da uno stato a un altro attraverso dei metodi di callback. Un'activity può trovarsi in uno dei seguenti stati:
- ACTIVE: l'activity è visibile all'utente che può quindi interagire con la stessa;
- PAUSED: l'activity non è attiva e può essere visibile in parte (attraverso effetti di trasparenza);
- STOPPED: l'activity non è né attiva e né visibile;
Se l'activity si trova nello stato PAUSED o STOPPED può essere terminata dal sistema operativo (attraverso il metodo finish()
) per liberare le risorse impegnate a favore dell'activity in esecuzione (nello stato ACTIVE). Se la stessa activity viene poi richiesta dall'utente il sistema operativo procederà alla sua creazione, ripristinando i valori salvati.
Un'activity può trovarsi nello stato ACTIVE subito dopo l'istanza della stessa, attraverso i metodi onCreate()
, onStart()
e onResume()
, eseguiti in successione. L'esecuzione di un'altra activity pone l'activity fin li usata dall'utente nello stato PAUSED, attraverso il metodo onPause()
, ed esegue una nuova activity (attraverso la sequenza di metodi detti prima) oppure ne ripristina una già esistente. Tale ripristino può avvenire invocando il metodo onResume()
, se l'applicazione da ripristinare è nello stato PAUSED, oppure il metodo onRestart()
(seguito dai metodi onStart()
e onResume()
) se l'applicazione è invece nello stato STOPPED. Un'activity transita dallo stato PAUSED allo stato STOPPED attraverso il metodo onStop()
. Per garantire all'utente la disponibilità dell'activity richiesta la transizione da PAUSED a STOPPED non avviene immediatamente. Il sistema operativo, infatti, ferma l'activity in esecuzione facendola transitare da RUNNING a PAUSED, quindi avvia l'activity richiesta dall'utente e solo dopo si preoccupa di ultimare il lavoro, fermando la precedente activity da PAUSED a STOPPED. Un'activity nello stato STOPPED, infine, rilascia le risorse impegnate attraverso il metodo onDestroy()
.
Metodi di callback:
onCreate()
: viene chiamato quando l'activity è creata per la prima volta. E' qui che invocando il metodo findViewById()
possiamo intercettare i componenti inseriti nel layout, con setContentView()
, e programmarne i comportamenti. L'oggetto Bundle
permette di ripristinare lo stato dell'activity, se quest'ultima è stata chiusa;onStart()
: viene invocato prima che l'activity diventi visibile all'utente;onResume()
: viene invocato prima che l'activity possa interagire con l'utente;onPause()
: viene invocato quando un'activity sta per essere messa in background, prima di ripristinare l'activity chiesta dall'utente. E' preferibile non appesantire questo metodo poiché finché esso non termina il sistema operativo non avvia l'activity richiesta! Meglio salvare lo stato con onSaveInstanceState(Bundle obj)
;onStop()
: viene invocato dal sistema operativo quando l'applicazione non è più usata dall'utente;onDestroy()
: viene invocato prima di terminare l'applicazione. Può essere invocato dall'utente per terminare l'applicazione (metodo finish()
) o dal sistema operativo per liberare risorse;onRestart()
: viene chiamato prima del metodo onStart()
per ripristinare un'activity dallo stato STOPPED;onSaveInstanceState(Bundle obj)
: viene invocato per salvare informazioni sullo stato dell'activity che verrà fermata;onRestoreInstanceState(Bundle obj)
: viene invocato per ripristinare i valori salvati;
Un'activity di un'applicazione non necessariamente deve implementare tutti i metodi di callback. Il ciclo di vita di un'applicazione Android può essere verificato attraverso un'applicazione che sovrascrivendo tutti i metodi di callback detti sopra mostri all'interno della finestra LogCat (di Eclipse) l'alternanza dei metodi coinvolti nell'utilizzo dell'applicazione. Trovate
qui tale applicazione, due activity che regolano il valore di un contatore. La prima permette di aumentarne il valore attraverso la pressione di un bottone, oppure di avviare la seconda activity. Un altro bottone permette di chiudere l'applicazione. La seconda attività eredita dalla precedente activity lo stato del contatore e ne diminuisce il valore, oltre a permettere come la prima la chiusura dell'applicazione.
La stampa di messaggi di log avviene invocando nei metodi di callback il metodo Log, del package android.util.Log
. A tale metodo occorre passare una stringa per etichettare con un tag i messaggi (variabile tag
delle due activity) e una stringa che rappresenterà il messaggio da stampare. Ogni metodo di callback deve necessariamente chiamare il metodo della classe padre (per l'ereditarietà), con la parola chiave super
. I bottoni dei layout applicati alle activity vengono rintracciati attraverso il metodo findViewById()
. Nei metodi onSaveInstanceState(Bundle outState)
e onRestoreInstanceState(Bundle savedInstanceState)
vengono, rispettivamente, salvati e ripristinati i valori usati nell'applicazione. Il passaggio da un activity a un'altra avviene attraverso la definizione di un Intent
. Ogni activity è in grado di svolgere un determinato lavoro e può dunque rispondere all'esigenza di un'altra applicazione in esecuzione. Questo permette di riutilizzare componenti già scritti! Nel codice dell'applicazione il passaggio alla seconda activity avviene con le seguenti istruzioni:
Intent intent=new Intent(LifecycleActivity.this,LifecycleSubActivity.class);
intent.putExtra("status",status);
startActivity(intent)
dove viene passato anche lo stato del contatore, con putExtra()
. La seconda activity va dichiarata all'interno del manifesto dell'applicazione, attraverso il tag activity. L'attributo android:name
del tag xml specifica il nome dell'activity da aggiungere all'applicazione. Avviando l'activity e seguendo l'output della finestra LogCat possiamo subito confermare l'invocazione, in sequenza, dei metodi onCreat()
, onStart()
e onResume()
.
Vi consiglio di applicare un filtro all'output di LogCat, usando proprio la stringa tag
definita nelle due activity! Cliccando sul bottone exit leggeremo l'invocazione dei metodi onPause()
, onStop()
e onDestroy()
.
Avviamo nuovamente l'applicazione, modifichiamo il valore del contatore e invochiamo adesso la seconda activity (con il bottone Del). Nel LogCat leggeremo, come prima, i metodi della prima activity, quindi noteremo la presenza di onPause()
per la prima activity e subito dopo i metodi onCreate()
, onStart()
e onResume()
per la seconda activity. Per la prima activity leggeremo ora la presenza del metodo onStop()
.
Premendo il tasto back del dispositivo leggeremo la presenza di onPause()
per la seconda activity, quindi onRestart()
, onStart()
ed infine onResume()
per la prima activity (che è già stata creata prima). Per la seconda activity leggeremo, poi, la presenza di onStop()
. Nell'output di LogCat noteremo inoltre la presenza dei metodi per salvare e ripristinare la variabile contatore. La seconda activity, infatti, non salva la variabile modificata (modificate il codice affinché ciò avvenga).