Tasks e stack posteriore

Un'attività è un insieme di attività con cui gli utenti interagiscono quando tentano di svolgere un'azione nella tua app. Queste attività sono disposte in uno stack chiamato stack back (back stack) nell'ordine in cui viene aperta ciascuna attività.

Ad esempio, un'app email potrebbe avere un'attività per mostrare un elenco di nuovi messaggi. Quando l'utente seleziona un messaggio, si apre una nuova attività per visualizzarlo. Questa nuova attività viene aggiunta allo stack di backup. Quando l'utente tocca Indietro o tocca Indietro, la nuova attività viene terminata e spuntata dall'elenco filtri.

Ciclo di vita di un'attività e del suo stack posteriore

La schermata Home del dispositivo è il punto di partenza per la maggior parte delle attività. Quando un utente tocca l'icona di un'app o di una scorciatoia in Avvio applicazioni o nella schermata Home, l'attività dell'app viene messa in primo piano. Se non esistono attività per l'app, viene creata una nuova attività e l'attività principale dell'app si apre come attività principale nello stack.

Quando l'attività corrente ne inizia un'altra, la nuova attività viene inserita in cima allo stack e viene evidenziata. L'attività precedente rimane nell'elenco, ma viene interrotta. Quando un'attività viene interrotta, il sistema conserva lo stato corrente dell'interfaccia utente. Quando l'utente esegue l'azione indietro, l'attività corrente viene estratta dall'alto dello stack ed eliminata. L'attività precedente riprende e lo stato precedente dell'interfaccia utente viene ripristinato.

Le attività nello stack non vengono mai riorganizzate, ma vengono trasferite e inviate dallo stack solo quando vengono avviate dall'attività corrente e ignorate dall'utente tramite il gesto o il pulsante Indietro. Di conseguenza, lo stack posteriore opera come struttura di oggetti last in, first out. La Figura 1 mostra una sequenza temporale con attività che vengono spinte ed estratte da uno stack precedente.

Figura 1. Una rappresentazione del modo in cui ogni nuova attività in un'attività aggiunge un elemento allo stack posteriore. Quando l'utente tocca o fa un gesto Indietro, l'attività corrente viene eliminata e quella precedente riprende.

Mentre l'utente continua a toccare o a eseguire il gesto Indietro, ogni attività nell'elenco viene visualizzata per mostrare quella precedente, finché l'utente non torna alla schermata Home o a qualsiasi attività in esecuzione quando è iniziata. Quando tutte le attività vengono rimosse dallo stack, l'attività non esiste più.

Comportamento del tocco indietro per le attività dell'avvio app root

Le attività di Avvio app radice sono attività che dichiarano un filtro di intent sia con ACTION_MAIN sia con CATEGORY_LAUNCHER. Queste attività sono uniche perché fungono da punti di ingresso alla tua app da Avvio applicazioni e vengono utilizzate per avviare un'attività.

Quando un utente tocca o fa un gesto Indietro da un'attività di avvio applicazioni principale, il sistema gestisce l'evento in modo diverso a seconda della versione di Android installata sul dispositivo.

Comportamento del sistema su Android 11 e versioni precedenti
Il sistema termina l'attività.
Comportamento del sistema su Android 12 e versioni successive

Il sistema sposta l'attività e la relativa attività in background anziché completarla. Questo comportamento corrisponde al comportamento predefinito del sistema quando si esce da un'app utilizzando il pulsante Home o il gesto.

Nella maggior parte dei casi, questo comportamento significa che gli utenti possono ripristinare più rapidamente l'app da uno stato caldo, anziché dover riavviare completamente l'app da uno stato a freddo.

Se devi fornire una navigazione a ritroso personalizzata, ti consigliamo di utilizzare le API AndroidX Activity anziché eseguire l'override di onBackPressed(). Le API AndroidX Activity si riferiscono automaticamente al comportamento di sistema appropriato se non ci sono componenti che intercettano il sistema Back Tap.

Tuttavia, se l'app esegue l'override di onBackPressed() per gestire la navigazione posteriore e completare l'attività, aggiorna l'implementazione in modo che venga richiamata a super.onBackPressed() anziché terminare. La chiamata a super.onBackPressed() sposta l'attività e la relativa attività in background, quando opportuno, e fornisce agli utenti un'esperienza di navigazione più coerente in tutte le app.

Attività in background e in primo piano

Figura 2. Due attività: l'attività B riceve l'interazione dell'utente in primo piano, mentre l'attività A è in background, in attesa di essere ripresa.

Un'attività è un'unità coesa che può essere spostata in sfondo quando un utente inizia una nuova attività o passa alla schermata Home. Mentre è in background, tutte le attività nell'attività vengono interrotte, ma lo stack posteriore dell'attività rimane invariato: l'attività perde lo stato attivo mentre viene eseguita un'altra attività, come mostrato nella Figura 2. Un'attività può quindi tornare in primo piano in modo che gli utenti possano riprendere da dove avevano interrotto.

Considera il seguente flusso per l'attività A attuale con tre attività nel proprio stack, incluse due nell'attività corrente:

  1. L'utente utilizza il pulsante Home o il gesto, quindi avvia una nuova app da Avvio applicazioni.

    Quando appare la schermata Home, l'attività A passa in background. Quando viene avviata la nuova app, il sistema avvia un'attività per quell'app (attività B) con il proprio stack di attività.

  2. Dopo aver interagito con l'app, l'utente torna di nuovo alla schermata Home e seleziona l'app che ha avviato inizialmente l'attività A.

    Ora l'attività A è in primo piano: tutte e tre le attività nello stack sono intatte e l'attività in cima allo stack riprende. A questo punto, l'utente può anche tornare all'attività B andando alla schermata Home e selezionando l'icona dell'app che ha avviato l'attività o selezionando l'attività dell'app dalla schermata Recenti.

Più istanze di attività

Figura 3. È possibile creare più istanze di una singola attività più volte.

Poiché le attività nello stack di backup non vengono mai riorganizzate, se l'app consente agli utenti di avviare una determinata attività da più di un'attività, viene creata una nuova istanza di tale attività e ne viene eseguito il push nello stack, anziché portare all'inizio qualsiasi istanza precedente dell'attività. Di conseguenza, è possibile che venga creata un'istanza più volte per un'attività nell'app, anche da attività diverse, come mostrato nella Figura 3.

Se l'utente torna indietro utilizzando il pulsante Indietro o il gesto Indietro, le istanze dell'attività vengono mostrate nell'ordine in cui sono state aperte, ciascuna con il proprio stato dell'interfaccia utente. Tuttavia, puoi modificare questo comportamento se non vuoi che un'attività venga creata più di una volta. Per ulteriori informazioni in merito, consulta la sezione relativa alla gestione delle attività.

Ambienti multi-finestra

Quando le app vengono eseguite contemporaneamente in un ambiente multi-finestra, supportato in Android 7.0 (livello API 24) e versioni successive, il sistema gestisce le attività separatamente per ogni finestra. Ogni finestra può includere più attività. Lo stesso vale per le app Android in esecuzione sui Chromebook: il sistema gestisce attività, o gruppi di attività, su base finestra.

Riepilogo del ciclo di vita

Per riepilogare il comportamento predefinito di attività e attività:

  • Quando l'attività A inizia l'attività B, l'attività A viene interrotta, ma il sistema conserva il suo stato, ad esempio la posizione di scorrimento e l'eventuale testo inserito nei moduli. Se l'utente tocca o utilizza il gesto Indietro nell'attività B, l'attività A viene ripresa e il suo stato viene ripristinato.

  • Quando l'utente abbandona un'attività utilizzando il pulsante Home o il gesto, l'attività corrente viene interrotta e la relativa attività viene spostata in background. Il sistema conserva lo stato di ogni attività nell'attività. Se in un secondo momento l'utente riprende l'attività selezionando l'icona di avvio dell'attività che l'ha avviata, l'attività viene mostrata in primo piano e riprende l'attività in cima all'elenco filtri.

  • Se l'utente tocca o fa un gesto Indietro, l'attività corrente viene estratta dall'elenco e eliminata. L'attività precedente nello stack viene ripresa. Quando un'attività viene eliminata, il sistema non conserva lo stato dell'attività.

    Questo comportamento è diverso per le attività dell'Avvio app root, quando l'app è in esecuzione su un dispositivo con Android 12 o versioni successive.

  • Puoi creare istanze di attività più volte, anche da altre attività.

Gestite le attività

Android gestisce le attività e lo stack posteriore posizionando tutte le attività avviate in successione nella stessa attività, in uno stack ultime in entrata e in uscita. Questo funziona molto bene per la maggior parte delle app e di solito non devi preoccuparti di come le tue attività sono associate alle attività o di come si trovano nello stack posteriore.

Tuttavia, potresti decidere di interrompere il comportamento normale. Ad esempio, potresti volere che un'attività nella tua app inizi una nuova attività all'avvio, anziché essere inserita nell'attività corrente. In alternativa, quando avvii un'attività, potresti voler portare avanti un'istanza esistente, anziché creare una nuova istanza sopra lo stack di back-forward. Oppure potresti voler eliminare tutte le attività dallo stack di riserva, ad eccezione dell'attività principale, quando l'utente abbandona l'attività.

Puoi svolgere queste e altre operazioni utilizzando gli attributi nell'elemento manifest <activity> e i flag nell'intent che passi a startActivity().

Questi sono gli attributi <activity> principali che puoi utilizzare per gestire le attività:

Ecco i principali flag di intent che puoi utilizzare:

Le seguenti sezioni descrivono come utilizzare questi attributi del file manifest e i flag di intent per definire il modo in cui le attività vengono associate alle attività e il loro comportamento nello back stack.

Vengono inoltre trattate le considerazioni relative a come le attività e le attività vengono rappresentate e gestite nella schermata Recenti. Di solito, lasci che il sistema definisca il modo in cui l'attività e le attività vengono rappresentate nella schermata Recenti e non è necessario modificare questo comportamento. Per ulteriori informazioni, consulta la schermata Recenti.

Definisci le modalità di avvio

Le modalità di avvio consentono di definire in che modo una nuova istanza di un'attività viene associata all'attività corrente. Puoi definire le modalità di lancio in due modi, descritti nelle sezioni che seguono:

Quindi, se l'attività A avvia l'attività B, l'attività B può definire nel manifest la modalità di associazione all'attività corrente e l'attività A può utilizzare un flag di intent per richiedere in che modo l'attività B può essere associata all'attività corrente.

Se entrambe le attività definiscono il modo in cui l'Attività B viene associata a un'attività, la richiesta dell'attività A, come definita nell'intent, viene rispettata rispetto alla richiesta dell'attività B, come definita nel manifest.

Definire le modalità di avvio utilizzando il file manifest

Quando dichiari un'attività nel file manifest, puoi specificare in che modo l'attività viene associata a un'attività utilizzando l'attributo launchMode dell'elemento <activity>.

Esistono cinque modalità di lancio che puoi assegnare all'attributo launchMode:

  1. "standard"
    La modalità predefinita. Il sistema crea una nuova istanza dell'attività nell'attività da cui è stata avviata e vi indirizza l'intent. L'attività può essere verificata più volte, ogni istanza può appartenere ad attività diverse e un'attività può avere più istanze.
  2. "singleTop"
    Se esiste già un'istanza dell'attività nella parte superiore dell'attività corrente, il sistema instrada l'intent a quell'istanza mediante una chiamata al relativo metodo onNewIntent(), anziché creare una nuova istanza dell'attività. L'attività è infondata più volte, ogni istanza può appartenere ad attività diverse e un'attività può avere più istanze (ma solo se l'attività nella parte superiore dello stack arretrato non è un'istanza esistente dell'attività).

    Ad esempio, supponi che lo stack precedente di un'attività sia costituito dall'attività principale A con le attività B, C e D in cima (quindi lo stack è A-B-C-D, con D in cima). arriva un intent per un'attività di tipo D. Se D ha la modalità di avvio predefinita "standard", viene avviata una nuova istanza della classe e lo stack diventa A-B-C-D-D. Tuttavia, se la modalità di avvio di D è "singleTop", l'istanza esistente di D riceve l'intent tramite onNewIntent(), perché si trova in cima allo stack, mentre lo stack rimane A-B-C-D. Se, invece, arriva un intent per un'attività di tipo B, viene aggiunta una nuova istanza di B allo stack anche se la sua modalità di avvio è "singleTop".

  3. "singleTask"
    Il sistema crea l'attività all'origine di una nuova attività o la individua in un'attività esistente con la stessa affinità. Se un'istanza dell'attività esiste già, il sistema instrada l'intent all'istanza esistente tramite una chiamata al relativo metodo onNewIntent(), anziché creare una nuova istanza. Nel frattempo, tutte le altre attività su di esso vengono distrutte.
  4. "singleInstance".
    Il comportamento è uguale a quello di "singleTask", tranne per il fatto che il sistema non avvia altre attività nell'attività che include l'istanza. L'attività è sempre l'unico e unico membro della sua attività. Tutte le attività avviate da questa si aprono in un'attività separata.
  5. "singleInstancePerTask".
    L'attività può essere eseguita solo come attività principale, ovvero la prima attività che l'ha creata, quindi può esistere una sola istanza di questa attività in un'attività. A differenza della modalità di avvio singleTask, questa attività può essere avviata in più istanze e in attività diverse se è impostato il flag FLAG_ACTIVITY_MULTIPLE_TASK o FLAG_ACTIVITY_NEW_DOCUMENT.

Come ulteriore esempio, l'app Browser Android dichiara che l'attività del browser web si apre sempre in una propria attività specificando la modalità di avvio singleTask nell'elemento <activity>. Ciò significa che se la tua app invia un intent per l'apertura del browser Android, la sua attività non viene inserita nella stessa attività dell'app. Viene avviata una nuova attività per il browser oppure, se per il browser è già in esecuzione un'attività in background, tale attività viene inoltrata per gestire il nuovo intent.

Indipendentemente dal fatto che un'attività inizi in una nuova attività o nella stessa attività da cui è iniziata, il pulsante Indietro e il gesto indirizzano sempre l'utente all'attività precedente. Tuttavia, se avvii un'attività che specifica la modalità di avvio di singleTask e esiste un'istanza di questa attività in un'attività in background, l'intera attività viene messa in primo piano. A questo punto, lo back stack include tutte le attività dell'attività portate in avanti in cima allo stack. La Figura 4 mostra questo tipo di scenario.

Figura 4. Una rappresentazione di come un'attività con modalità di avvio "singleTask" viene aggiunta allo stack posteriore. Se l'attività fa già parte di un'attività in background con un proprio back stack, viene visualizzato anche l'intero stack back, in cima all'attività corrente.

Per ulteriori informazioni sull'utilizzo delle modalità di avvio nel file manifest, consulta la documentazione dell'elemento <activity>.

Definisci le modalità di avvio utilizzando i flag di intent

Quando avvii un'attività, puoi modificare l'associazione predefinita di un'attività alla relativa attività includendo i flag nell'intent inviato a startActivity(). Di seguito sono riportati i flag che puoi utilizzare per modificare il comportamento predefinito:

FLAG_ACTIVITY_NEW_TASK

Il sistema avvia l'attività in una nuova attività. Se è già in esecuzione per l'attività avviata, questa viene messa in primo piano con l'ultimo stato ripristinato e l'attività riceve il nuovo intent in onNewIntent().

Questo produce lo stesso comportamento del valore "singleTask" launchMode discusso nella sezione precedente.

FLAG_ACTIVITY_SINGLE_TOP

Se l'attività avviata è quella attuale, nella parte superiore dello stack, l'istanza esistente riceve una chiamata a onNewIntent() anziché creare una nuova istanza dell'attività.

Questo produce lo stesso comportamento del valore "singleTop" launchMode discusso nella sezione precedente.

FLAG_ACTIVITY_CLEAR_TOP

Se l'attività avviata è già in esecuzione nell'attività corrente, invece di avviare una nuova istanza di quell'attività, il sistema elimina tutte le altre attività nell'attività corrente. L'intent viene pubblicato nell'istanza ripresa dell'attività, ora in cima, tramite onNewIntent().

Non esiste un valore per l'attributo launchMode che produce questo comportamento.

FLAG_ACTIVITY_CLEAR_TOP viene utilizzato più spesso in combinazione con FLAG_ACTIVITY_NEW_TASK. Se utilizzati insieme, questi flag individuano un'attività esistente in un'altra attività e la mettono in una posizione in cui può rispondere all'intent.

Gestire le affinità

Un'affinità indica l'attività a cui "preferisce" appartenere. Per impostazione predefinita, tutte le attività della stessa app hanno un'affinità tra loro: "preferiscono" essere incluse nella stessa attività.

Tuttavia, puoi modificare l'affinità predefinita per un'attività. Le attività definite in app diverse possono condividere un'affinità, mentre alle attività definite nella stessa app puoi assegnare affinità diverse.

Puoi modificare l'affinità di un'attività utilizzando l'attributo taskAffinity dell'elemento <activity>.

L'attributo taskAffinity prende un valore stringa che deve essere diverso dal nome del pacchetto predefinito dichiarato nell'elemento <manifest>, perché il sistema utilizza questo nome per identificare l'affinità predefinita dell'attività per l'app.

L'affinità entra in gioco in due circostanze:

  1. Quando l'intent che avvia un'attività contiene il flag FLAG_ACTIVITY_NEW_TASK.

    Per impostazione predefinita, viene avviata una nuova attività nell'attività che ha chiamato startActivity(). Viene inviato allo stesso stack posteriore del chiamante.

    Tuttavia, se l'intent trasmesso a startActivity() contiene il flag FLAG_ACTIVITY_NEW_TASK, il sistema cerca un'altra attività per ospitare la nuova attività. Spesso si tratta di un'attività nuova. ma non deve esserlo. Se esiste già un'attività con la stessa affinità della nuova attività, viene avviata l'attività in quell'attività. In caso contrario, avvia una nuova attività.

    Se questo flag causa l'inizio di una nuova attività da parte di un'attività e l'utente utilizza il pulsante Home o il gesto per uscire, l'utente deve poter tornare in un determinato modo. Alcune entità, come il gestore delle notifiche, avviano sempre attività in un'attività esterna, mai come parte delle proprie, quindi inseriscono sempre FLAG_ACTIVITY_NEW_TASK negli intent che passano a startActivity().

    Se un'entità esterna che potrebbe utilizzare questo flag può richiamare la tua attività, assicurati che l'utente disponga di un modo indipendente per tornare all'attività avviata, ad esempio mediante un'icona in Avvio applicazioni, in cui l'attività principale dell'attività ha un filtro di intent CATEGORY_LAUNCHER. Per ulteriori informazioni, consulta la sezione relativa all'avvio delle attività.

  2. Quando l'attributo allowTaskReparenting di un'attività è impostato su "true".

    In questo caso, l'attività può essere spostata dall'attività in cui inizia a quella per cui ha un'affinità quando diventa in primo piano.

    Ad esempio, supponi che un'attività che segnala le condizioni meteo in determinate città sia definita come parte di un'app di viaggi. Ha la stessa affinità di altre attività nella stessa app, l'affinità predefinita dell'app e può essere assegnata nuovamente a un'app con questo attributo.

    Quando una delle tue attività inizia l'attività reporter meteo, inizialmente appartiene alla stessa attività della tua attività. Tuttavia, quando l'attività dell'app di viaggio viene messa in primo piano, l'attività del reporter meteo viene riassegnata a questa attività e visualizzata al suo interno.

Cancella lo stack posteriore

Se l'utente abbandona un'attività per molto tempo, il sistema cancella tutte le attività, ad eccezione dell'attività principale. Quando l'utente torna all'attività, viene ripristinata solo l'attività principale. Il sistema si comporta in questo modo in base al presupposto che, dopo un periodo di tempo prolungato, gli utenti abbiano abbandonato ciò che stavano facendo prima e tornino all'attività per iniziare qualcosa di nuovo.

Per modificare questo comportamento, puoi utilizzare alcuni attributi di attività:

alwaysRetainTaskState
Quando questo attributo è impostato su "true" nell'attività principale di un'attività, il comportamento predefinito appena descritto non si verifica. L'attività conserva tutte le attività nel proprio stack anche dopo un lungo periodo di tempo.
clearTaskOnLaunch

Se questo attributo è impostato su "true" nell'attività principale di un'attività, quest'ultima viene cancellata dall'attività principale ogni volta che l'utente abbandona l'attività e torna all'attività. In altre parole, è il contrario di alwaysRetainTaskState. L'utente torna sempre all'attività nel suo stato iniziale, anche dopo essere uscito dall'attività solo per un momento.

finishOnTaskLaunch

Questo attributo è simile a clearTaskOnLaunch, ma opera su una singola attività, non su un'intera attività. Può inoltre causare il completamento di qualsiasi attività tranne quella principale. Se è impostato su "true", l'attività rimane parte dell'attività solo per la sessione corrente. Se l'utente abbandona l'attività e poi torna all'attività, quest'ultima non è più presente.

Avvia un'attività

Puoi impostare un'attività come punto di ingresso per un'attività assegnandole un filtro per intent con "android.intent.action.MAIN" come azione specificata e "android.intent.category.LAUNCHER" come categoria specificata:

<activity ... >
    <intent-filter ... >
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    ...
</activity>

Un filtro per intent di questo tipo comporta la visualizzazione di un'icona e di un'etichetta per l'attività in Avvio applicazioni, offrendo agli utenti un modo per avviare l'attività e per tornare all'attività creata in qualsiasi momento dopo l'avvio.

Questa seconda funzionalità è importante. Gli utenti devono essere in grado di uscire da un'attività e di accedervi di nuovo in un secondo momento utilizzando l'Avvio attività. Per questo motivo, utilizza solo le due modalità di avvio che contrassegnano le attività come ad avviare sempre un'attività, "singleTask" e "singleInstance", quando l'attività ha un filtro ACTION_MAIN e un CATEGORY_LAUNCHER.

Immagina, ad esempio, cosa potrebbe accadere se il filtro non fosse presente: un intent avvia un'attività "singleTask", avviando una nuova attività e l'utente trascorre del tempo a tale attività. L'utente usa quindi il pulsante Home o il gesto. L'attività viene ora inviata in background e non è visibile. Ora l'utente non ha modo di tornare all'attività perché non è rappresentata in Avvio applicazioni.

Per quei casi in cui non vuoi che l'utente possa tornare a un'attività, imposta l'elemento finishOnTaskLaunch dell'elemento <activity> su "true". Per ulteriori informazioni, consulta la sezione relativa allo svuotamento dello stack di supporto.

Ulteriori informazioni su come le attività e le attività sono rappresentate e gestite nella schermata Recenti sono disponibili nella schermata Recenti.

Altre risorse