back to top

Il ciclo di vita delle applicazioni Android e le activity

Abbiamo compreso che un’applicazione Android è costituita da diversi componenti. Questi elementi devono utilizzare le risorse del sistema sul quale risiedono consentendo però al sistema operativo e alle altre applicazioni di rimanere responsivi all’interazione con l’utente. Per ottenere questo risultato è fondamentale comprendere il ciclo di vita delle applicazioni e delle activity, ma anche il modo in cui un’applicazione può reagire ad un cambiamento di stato.

Ogni applicazione Android in esecuzione viene vista dal sistema come un processo separato e se il sistema riconosce che essa richiede una maggiore capacità vengono avviate azioni per la terminazione di processi non necessari e quindi l’aumento della memoria disponibile. Quando il sistema deve individuare i processi da terminare per ottenere questo obiettivo tiene in considerazione la priorità e lo stato di tutti i processi in esecuzione, creando la cosiddetta gerarchia di importanza. I processi vengono poi terminati partendo da quelli più in basso nella gerarchia e risalendo, finchè non vengono liberate le risorse necessarie.

In generale i processi possono trovarsi in uno dei seguenti cinque stati gerarchici

  • FOREGROUND PROCESS (priorità più alta)
  • VISIBLE PROCESS
  • SERVICE PROCESS
  • BACKGROUND PROCESS
  • EMPTY PROCESS (priorità più bassa)

FOREGROUND PROCESS

Questi processi hanno la priorità più alta e in un determinato momento su un dispositivo tipicamente ne sono attivi uno o due. Un processo si trova in questo stato se soddisfa uno dei seguenti criteri:

  • Ospita un’activity con la quale l’utente sta interagendo
  • Ospita un servizio legato ad un’activity con la quale l’utente sta interagendo
  • Ospita un servizio per il quale è stato segnalato che la terminazione potrebbe disturbare l’esperienza utente (user experience)

VISIBLE PROCESS

Si tratta di processi che contengono un’activity che è visibile all’utente ma con la quale l’utente non sta interagendo in quel momento.

SERVICE PROCESS

Processi che contengono un servizio che è stato già avviato ed è correntemente in esecuzione.

BACKGROUND PROCESS

Processi che contengono una o più activity che non sono attualmente visibili all’utente. I processi che si trovano in questo stato hanno un’alta probabilità di essere terminati nel caso in cui il sistema necessiti di memoria addizionale per i processi a priorità più elevata.

EMPTY PROCESS

Processi che non contengono alcuna applicazione attiva e vengono mantenuti in memoria pronti ad essere utilizzati per il nuovo lancio di applicazioni. Questi processi sono i primi ad essere terminati per liberare risorse.

La situazione si complica un po’ quando i processi dipendono uno dall’altro. Infatti Android quando si trova a determinare la priorità di un processo deve anche tenere in considerazione se quel processo sta in qualche modo servendo un altro processo a priorità più elevata ed in tal caso esso assume la priorità di quello che sta servendo.

Lo stato di un processo Android è strettamente determinato dallo stato delle activity e dei componenti che costituiscono l’applicazione che sta ospitando. Anche le activity passano attraverso differenti stati durante il ciclo di vita di un’applicazione ed il loro stato corrente è determinato in parte dalla loro posizione in quello che è chiamato Activity Stack.

Per ogni applicazione che viene avviata su un dispositivo Android il sistema mantiene appunto una struttura denominata Activity Stack. Quando un’applicazione viene lanciata la prima activity della stessa viene inserita nello stack. Quando viene avviata una seconda activity questa viene messa in cima allo stack e la prima viene spostata in basso. L’activity che si trova in cima è dunque quella attualmente attiva e quando termina viene espulsa dallo stack e distrutta. L’utente può terminarla ad esempio cliccando sul tasto Back per tornare ad un’activity precedente oppure l’activity stessa termina il suo compito e quindi viene eliminata dallo stack e distrutta dall’ambiente di esecuzione.

Un’activity può trovarsi in uno dei seguenti stati durante la sua esecuzione all’interno di un’applicazione:

Active/Running – L’activity è in cima all’Activity Stack, è visibile sullo schermo e sta interagendo con l’utente.

Paused – L’activity è visibile ma non è quella che sta interagendo con l’utente, magari perché è parzialmente oscurata da altre activity.

Stopped – L’activity non è visibile all’utente, è totalmente oscurata da altre activity.

Killed – L’activity è stata terminata e non è più presente nell’Activity Stack.

Ricapitolando quindi un’activity è essenzialmente una finestra che contiene l’interfaccia utente di un’applicazione ed il suo scopo è quello di permettere un’interazione con gli utenti. Un’applicazione può avere una o più activity e dal momento in cui un’activity compare sullo schermo al momento in cui scompare essa passa attraverso una serie di stati, il cosiddetto ciclo di vita (life cycle).

Per creare un’activity occorre definire una classe Java che estende la classe base AppCompatActivity

Tale classe definisce una serie di eventi che governano il ciclo di vita dell’ activity stessa:

onCreate – Si verifica quando l’activity viene creata

onStart – Si verifica quando l’activity diviene visibile all’utente

onResume – Si verifica quando l’activity avvia l’interazione con l’utente

onPause – Si verifica quando la corrente activity viene messa in pausa ed una precedente activity viene riattivata

onStop – Si verifica quando un’activity non è più visibile all’utente

onDestroy – Si verifica prima che l’activity venga distrutta dal sistema

onRestart – Si verifica quando l’activity viene arrestata e riavviata

Di seguito un’immagine che riassume il ciclo di vita di un’activity con la sequenza dei suddetti eventi

Come impostazione predefinita quando viene creata una nuova activity essa contiene già l’evento onCreate, il cui codice serve a visualizzare gli elementi dell’interfaccia utente.

Per gestire il comportamento che la nostra applicazione deve avere al verificarsi di questi eventi basta modificare la classe MainActivity con il seguente codice

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void onStart()
    {
        super.onStart();

    }

    public void onRestart()
    {
        super.onRestart();

    }

    public void onResume()
    {
        super.onResume();

    }

    public void onPause()
    {
        super.onPause();

    }

    public void onStop()
    {
        super.onStop();

    }

    public void onDestroy()
    {
        super.onDestroy();

    }
}

Un’activity tipicamente viene distrutta quando si clicca sul pulsante Back del dispositivo. Altre cosa da sottolineare è che quando un’activity viene avviata vengono sempre chiamati i metodi onStart e onResume, indipendentemente dal fatto che l’activity sia ripristinata da uno stato di pausa o creata nuovamente. Quando essa viene creata nuovamente viene ovviamente chiamato anche il metodo onCreate.

Detto questo, possiamo definire alcune semplici linee guida per lo sviluppo delle nostre applicazioni:

  • Utilizzare il metodo onCreate per creare ed istanziare gli oggetti che verranno utilizzati nella nostra applicazione
  • Utilizzare il metodo onResume per avviare ogni servizio o componente che necessita di essere eseguito mentre l’activity è in uso
  • Utilizzare il metodo onPause per terminare ogni servizio o componente non necessario mentre l’activity non è in uso
  • Utilizzare il metodo onDestroy per liberare risorse prima che l’activity sia distrutta

Vi ricordo che ogni activity contenuta in un’applicazione deve essere dichiarata nel file AndroidManifest.xml

Pubblicitร