Quando un utente naviga all'interno, uscire e tornare alla tua app,
Transizione di Activity
istanze nella tua app tramite
stati diversi nel loro ciclo di vita.
La classe Activity
prevede una serie di richiamate
che comunicano all'attività quando uno stato cambia o che
sistema sta creando, arrestando o riprendendo un'attività o distruggendo
il processo in cui risiede l'attività.
Nei metodi di callback del ciclo di vita, puoi dichiarare in che modo si comporta quando l'utente esce dall'attività e vi rientra. Ad esempio, se stai creando un video player in streaming, potresti mettere in pausa il video connessione di rete quando l'utente passa a un'altra app. Quando l'utente ritorna, puoi riconnetterti alla rete e consentire all'utente di riprendere la visione del video lo stesso punto.
Ogni callback ti consente di eseguire operazioni specifiche appropriato per un determinato cambiamento di stato. Svolgere il lavoro giusto con la giusta e gestire correttamente le transizioni rendono la tua app più solida e performante. Ad esempio, una buona implementazione dei callback del ciclo di vita può aiutare la tua app evita quanto segue:
- Arresto anomalo se l'utente riceve una chiamata o passa a un'altra chiamata mentre la utilizzi.
- Consumo di preziose risorse di sistema quando l'utente non sta attivamente utilizzandolo.
- Perdere i progressi dell'utente se esce dall'app e torna a in un secondo momento.
- Arresto anomalo o perdita dei progressi dell'utente quando lo schermo ruota tra orientamento orizzontale e verticale.
Questo documento spiega in dettaglio il ciclo di vita delle attività. Il documento inizia descrivendo il paradigma del ciclo di vita. A seguire, vengono spiegati tutti i richiami: cosa succede internamente durante l'esecuzione e cosa è necessario implementare durante questo processo.
Quindi introduce brevemente la relazione tra attività e la vulnerabilità di un processo all'eliminazione da parte del sistema. Infine, tratta diversi argomenti relativi alle transizioni gli stati dell'attività.
Per informazioni sulla gestione dei cicli di vita, incluse indicazioni sulla best practice, consulta Gestione dei cicli di vita con componenti sensibili al ciclo di vita e Salva stati dell'interfaccia utente. Per imparare a progettare un'app solida e di qualità per la produzione utilizzando le attività in combinazione con i componenti dell'architettura, vedi Guida all'architettura delle app.
Concetti sul ciclo di vita dell'attività
Per navigare nelle transizioni tra le fasi del ciclo di vita dell'attività,
La classe Activity
prevede un insieme principale di sei callback:
onCreate()
,
onStart()
,
onResume()
,
onPause()
,
onStop()
e
onDestroy()
. Il sistema richiama
ciascuno di questi callback quando l'attività entra in un nuovo stato.
La Figura 1 presenta una rappresentazione visiva di questo paradigma.
Quando l'utente inizia ad abbandonare l'attività, il sistema chiama dei metodi per smantellare l'attività. In alcuni casi, l'attività è solo parzialmente smantellato e ancora oggi in memoria, ad esempio quando l'utente passa un'altra app. In questi casi, l'attività può comunque tornare in primo piano.
Se l'utente torna all'attività, riprenderà dal punto in cui l'utente era stato interrotto. Con alcune eccezioni, le app sono limitato da avviare attività in esecuzione in background.
La probabilità che il sistema l'interruzione di un determinato processo, insieme alle attività in esso contenute, dipende dallo stato dell'attività in quel momento. Per ulteriori informazioni sulla relazione tra stato e la vulnerabilità all'esclusione, consulta la sezione relativa allo stato dell'attività e all'espulsione dalla memoria.
A seconda della complessità della tua attività, probabilmente non c'è bisogno a implementare tutti i metodi del ciclo di vita. Tuttavia, è importante che tu capire come funzionano e implementare quelle che consentono alla tua app di comportarsi come si aspettano gli utenti.
Callback del ciclo di vita
Questa sezione fornisce informazioni concettuali e sull'implementazione relative metodi di callback utilizzati durante il ciclo di vita dell'attività.
Alcune azioni appartengono ai metodi del ciclo di vita delle attività. Tuttavia, inserisci il codice che implementa le azioni di un componente dipendente anziché il metodo del ciclo di vita delle attività. Per farlo, devi avere per rendere il componente dipendente sensibile al ciclo di vita. Per scoprire come realizzare e sensibili al ciclo di vita dei componenti dipendenti, consulta Gestione dei cicli di vita con componenti sensibili al ciclo di vita.
onCreate()
Devi implementare questo callback, che si attiva quando il sistema crea per la prima volta il
attività. Al momento della creazione, l'attività passa allo stato Creata.
In onCreate()
esegui una logica di avvio dell'applicazione di base,
avviene una sola volta durante l'intera durata dell'attività.
Ad esempio,
l'implementazione di onCreate()
potrebbe associare i dati a elenchi, associare l'attività a un
ViewModel
,
e creare un'istanza di alcune variabili con ambito della classe. Questo metodo riceve
parametro savedInstanceState
, che è un valore Bundle
contenente lo stato salvato in precedenza dell'attività. Se l'attività ha
non è mai esistito prima, il valore dell'oggetto Bundle
è nullo.
Se hai un componente sensibile al ciclo di vita collegato al ciclo di vita
la tua attività, riceve
ON_CREATE
. Il metodo annotato con @OnLifecycleEvent
viene chiamato in modo che sia sensibile al ciclo di vita
può eseguire qualsiasi codice di configurazione necessario per lo stato di creazione.
Il seguente esempio del metodo onCreate()
mostra la configurazione di base dell'attività, ad esempio la dichiarazione dell'interfaccia utente
(definite in un file di layout XML), definendo le variabili membro e configurando
parte dell'interfaccia utente. In questo esempio, il file di layout XML trasmette il parametro
l'ID risorsa del file R.layout.main_activity
setContentView()
.
Kotlin
lateinit var textView: TextView // Some transient state for the activity instance. var gameState: String? = null override fun onCreate(savedInstanceState: Bundle?) { // Call the superclass onCreate to complete the creation of // the activity, like the view hierarchy. super.onCreate(savedInstanceState) // Recover the instance state. gameState = savedInstanceState?.getString(GAME_STATE_KEY) // Set the user interface layout for this activity. // The layout is defined in the project res/layout/main_activity.xml file. setContentView(R.layout.main_activity) // Initialize member TextView so it is available later. textView = findViewById(R.id.text_view) } // This callback is called only when there is a saved instance previously saved using // onSaveInstanceState(). Some state is restored in onCreate(). Other state can optionally // be restored here, possibly usable after onStart() has completed. // The savedInstanceState Bundle is same as the one used in onCreate(). override fun onRestoreInstanceState(savedInstanceState: Bundle?) { textView.text = savedInstanceState?.getString(TEXT_VIEW_KEY) } // Invoked when the activity might be temporarily destroyed; save the instance state here. override fun onSaveInstanceState(outState: Bundle?) { outState?.run { putString(GAME_STATE_KEY, gameState) putString(TEXT_VIEW_KEY, textView.text.toString()) } // Call superclass to save any view hierarchy. super.onSaveInstanceState(outState) }
Java
TextView textView; // Some transient state for the activity instance. String gameState; @Override public void onCreate(Bundle savedInstanceState) { // Call the superclass onCreate to complete the creation of // the activity, like the view hierarchy. super.onCreate(savedInstanceState); // Recover the instance state. if (savedInstanceState != null) { gameState = savedInstanceState.getString(GAME_STATE_KEY); } // Set the user interface layout for this activity. // The layout is defined in the project res/layout/main_activity.xml file. setContentView(R.layout.main_activity); // Initialize member TextView so it is available later. textView = (TextView) findViewById(R.id.text_view); } // This callback is called only when there is a saved instance previously saved using // onSaveInstanceState(). Some state is restored in onCreate(). Other state can optionally // be restored here, possibly usable after onStart() has completed. // The savedInstanceState Bundle is same as the one used in onCreate(). @Override public void onRestoreInstanceState(Bundle savedInstanceState) { textView.setText(savedInstanceState.getString(TEXT_VIEW_KEY)); } // Invoked when the activity might be temporarily destroyed; save the instance state here. @Override public void onSaveInstanceState(Bundle outState) { outState.putString(GAME_STATE_KEY, gameState); outState.putString(TEXT_VIEW_KEY, textView.getText()); // Call superclass to save any view hierarchy. super.onSaveInstanceState(outState); }
In alternativa alla definizione del file XML e passarlo a setContentView()
,
puoi creare nuovi oggetti View
nel tuo codice attività e creare un
per visualizzare la gerarchia inserendo nuovi oggetti View
in un
ViewGroup
. Puoi quindi utilizzare questo layout passando il parametro
principale da ViewGroup
a setContentView()
.
Per ulteriori informazioni sulla creazione di un'interfaccia utente, consulta
interfaccia utente.
La tua attività non rimane in Creati
stato. Al termine dell'esecuzione del metodo onCreate()
, l'attività entra nel campo Iniziata
e il sistema chiama onStart()
e onResume()
di metodi in
successione.
onStart()
Quando l'attività passa allo stato Iniziata, il sistema
richiama onStart()
.
Questa chiamata rende l'attività visibile all'utente come
l'app si prepara affinché l'attività entri in primo piano e diventi interattiva.
Ad esempio, in questo metodo il codice che mantiene
l'inizializzazione dell'interfaccia utente.
Quando l'attività passa allo stato Iniziata, qualsiasi componente sensibile al ciclo di vita collegato
al ciclo di vita dell'attività riceve
Evento ON_START
.
Il metodo onStart()
viene completato
rapidamente e, come per lo stato Creato, l'attività non rimane
nello stato Iniziato. Al termine del callback, l'attività inserisce la
Lo stato Riprendi e il sistema richiama il metodo
onResume()
.
onRiprendi()
Quando l'attività passa allo stato Ripresa, l'attività passa in primo piano.
il sistema richiama onResume()
di Google. Questo è lo stato in cui l'app
interagisce con l'utente. L'app rimane in questo stato finché non succede qualcosa a
distoglie l'attenzione dall'app, ad esempio il dispositivo che riceve una telefonata, l'utente
la navigazione a un'altra attività o lo spegnimento dello schermo del dispositivo.
Quando l'attività passa allo stato Ripresa, qualsiasi componente sensibile al ciclo di vita legato
al ciclo di vita dell'attività riceve
ON_RESUME
. È qui che i componenti del ciclo di vita possono abilitare
qualsiasi funzionalità debba essere eseguita
il componente sia visibile e in primo piano, ad esempio l'avvio di una fotocamera
l'anteprima.
Quando si verifica un evento invasivo, l'attività entra nello stato In pausa
e il sistema richiama lo stato
Chiamata onPause()
.
Se l'attività torna a
lo stato Ripreso dallo stato In pausa, il sistema richiama nuovamente
onResume()
. Per questo motivo, implementa
onResume()
per inizializzare i componenti che rilasci durante
onPause()
e di eseguire qualsiasi altra
inizializzazioni che devono avvenire ogni volta che l'attività entra nel
stato.
Ecco un esempio di un componente sensibile al ciclo di vita che accede alla videocamera quando
il componente riceve l'evento ON_RESUME
:
Kotlin
class CameraComponent : LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun initializeCamera() { if (camera == null) { getCamera() } } ... }
Java
public class CameraComponent implements LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) public void initializeCamera() { if (camera == null) { getCamera(); } } ... }
Il codice precedente inizializza la fotocamera una volta che
LifecycleObserver
riceve l'evento ON_RESUME
. In modalità multi-finestra, invece, le tue attività
potrebbe essere completamente visibile anche quando è nello stato In pausa. Ad esempio, quando
l'app è in modalità multi-finestra e l'utente tocca la finestra che non
contengono la tua attività, l'attività passa allo stato In pausa.
Se
vuoi che la videocamera sia attiva solo quando l'app è ripresa (visibile
e attiva in primo piano), quindi inizializza la fotocamera dopo il
ON_RESUME
evento
dimostrato in precedenza. Se vuoi mantenere attiva la videocamera durante l'attività
è In pausa ma visibile, ad esempio in modalità multi-finestra,
inizializza la fotocamera dopo l'evento ON_START
.
Tuttavia, avere la videocamera mentre l'attività è in pausa potrebbe negare l'accesso alla videocamera a un'altra App ripresa in modalità multi-finestra. A volte è necessario mantenere videocamera attiva mentre la tua attività è in pausa, ma in realtà potrebbe peggiorare la qualità in generale l'esperienza utente.
Per questo motivo, valuta attentamente il punto in cui del loro ciclo di vita è più appropriato assumere il controllo delle risorse il contesto della modalità multi-finestra. Per ulteriori informazioni sul supporto della modalità multi-finestra vedi Supporto multi-finestra.
Indipendentemente dall'evento di compilazione che scegli di eseguire
di inizializzazione, assicurati di utilizzare il ciclo di vita corrispondente
per rilasciare la risorsa. Se inizializzati qualcosa dopo
l'evento ON_START
, rilasciarlo o terminarlo dopo il
Evento ON_STOP
. Se
vengono inizializzate dopo l'evento ON_RESUME
, rilasciate dopo
Evento ON_PAUSE
.
Lo snippet di codice precedente inserisce il codice di inizializzazione della fotocamera in una
basato sul ciclo di vita. Puoi invece inserire questo codice direttamente nell'attività
callback del ciclo di vita, come onStart()
e
onStop()
, ma sconsigliamo di farlo. Aggiunta di questa logica
a un componente indipendente che riconosce il ciclo di vita e ti consente di riutilizzarlo
in più attività senza dover duplicare il codice. Per scoprire come creare un componente sensibile al ciclo di vita, consulta
Gestione dei cicli di vita con componenti sensibili al ciclo di vita.
onPause()
Il sistema chiama questo metodo come prima indicazione che l'utente sta uscendo la tua attività, anche se non sempre significa che questa sia stata distrutta. Indica che l'attività non è più in primo piano, ma è sono ancora visibili se l'utente è in modalità multi-finestra. Esistono diversi motivi per cui un'attività può entrare questo stato:
- Un evento che interrompe l'esecuzione dell'app, come descritto nella sezione relativa alle il callback onResume() mette in pausa l'attività corrente. Questo è il tipo di comportamento più comune per verificare se è così.
- In modalità multi-finestra, solo un'app è attiva in qualsiasi momento e il sistema mette in pausa tutte le altre app.
- L'apertura di una nuova attività semitrasparente, ad esempio una finestra di dialogo, mette in pausa l'attività che copre. Purché l'attività è parzialmente visibile ma non a fuoco, rimangono in pausa.
Quando un'attività passa allo stato In pausa, qualsiasi componente sensibile al ciclo di vita legato
al ciclo di vita dell'attività riceve
Evento ON_PAUSE
. È qui che entrano in gioco
i componenti del ciclo di vita possono interrompere qualsiasi funzionalità
mentre il componente non è in primo piano, ad esempio interrompendo una videocamera
l'anteprima.
Utilizza il metodo onPause()
per mettere in pausa o
regolare le operazioni che non possono continuare o che potrebbero
continuare con la moderazione
mentre Activity
è in stato In pausa e che tu
che riprendono a breve.
Puoi anche utilizzare il metodo onPause()
per
rilasciare risorse di sistema, handle ai sensori (come GPS) o qualsiasi risorsa
influisce sulla durata della batteria quando l'attività è in pausa e l'utente non
ne hanno bisogno.
Tuttavia, come citato nella sezione relativa a onResume()
, un
l'attività potrebbe essere ancora completamente visibile se l'app è in modalità multi-finestra.
Potresti usare onStop()
anziché onPause()
per rilasciare o regolare completamente
Risorse e operazioni relative all'interfaccia utente per un supporto migliore della modalità multi-finestra.
Il seguente esempio di LifecycleObserver
la reazione all'evento ON_PAUSE
è la controparte dell'evento precedente
Esempio di evento ON_RESUME
, con il rilascio della fotocamera che si inizializza dopo
viene ricevuto l'evento ON_RESUME
:
Kotlin
class CameraComponent : LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) fun releaseCamera() { camera?.release() camera = null } ... }
Java
public class JavaCameraComponent implements LifecycleObserver { ... @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) public void releaseCamera() { if (camera != null) { camera.release(); camera = null; } } ... }
In questo esempio il codice di rilascio della fotocamera viene inserito dopo il
LifecycleObserver
riceve l'evento ON_PAUSE
.
onPause()
l'esecuzione è molto breve e
non offre necessariamente tempo sufficiente per eseguire le operazioni di salvataggio. Per questo
motivo, non usare onPause()
per salvare l'applicazione o l'utente
effettuare chiamate di rete o eseguire transazioni di database. Un simile funzionamento potrebbe non
prima del completamento del metodo.
Esegui invece operazioni di arresto per carichi intensivi durante
onStop()
. Per ulteriori informazioni
sulle operazioni adatte a eseguire
onStop()
, consulta la sezione successiva. Per ulteriori informazioni sul salvataggio
vedi la sezione relativa al salvataggio e al ripristino dello stato.
Completamento del metodo onPause()
non significa che l'attività lascia lo stato In pausa. Piuttosto, l'attività
rimane in questo stato finché l'attività non riprende o non diventa completamente
invisibile all'utente. Se l'attività riprende, il sistema richiama di nuovo
il callback onResume()
.
Se
l'attività torna dallo stato In pausa a quello Ripresa, il sistema mantiene
l'istanza Activity
residente in memoria, richiamando
per quell'istanza quando il sistema richiama onResume()
.
In questo scenario, non è necessario reinizializzare i componenti creati durante
metodi di callback che portano allo stato Ripreso. Se l'attività diventa
completamente invisibile, il sistema chiama
onStop()
.
onStop()
Quando la tua attività non è più visibile all'utente, inserisce il
Arrestato e il sistema richiama il
Chiamata onStop()
. Questo può verificarsi quando un'attività appena avviata copre l'intero schermo. La
il sistema chiama anche onStop()
quando l'attività termina e sta per essere interrotta.
Quando l'attività passa allo stato Interrotto, qualsiasi componente sensibile al ciclo di vita legato
al ciclo di vita dell'attività riceve
Evento ON_STOP
. È qui che entrano in gioco
i componenti del ciclo di vita possono interrompere qualsiasi funzionalità
mentre il componente non è visibile
sullo schermo.
Nel metodo onStop()
, rilascia o regola
e risorse che non sono necessarie quando l'app non è visibile all'utente. Ad esempio, la tua app potrebbe
metti in pausa le animazioni o passa dagli aggiornamenti della posizione granulari a quelli meno granulari. Utilizzo
onStop()
anziché onPause()
significa che il lavoro relativo all'interfaccia utente continua anche se l'utente sta visualizzando la tua attività in modalità multi-finestra
.
Usa anche onStop()
di eseguire operazioni di arresto relativamente
ad alta intensità di CPU. Ad esempio, se
non puoi trovare un momento migliore per salvare le informazioni in un database,
potresti farlo durante onStop()
. La
l'esempio seguente mostra un'implementazione
onStop()
che salva i contenuti di un
bozza di nota per l'archiviazione permanente:
Kotlin
override fun onStop() { // Call the superclass method first. super.onStop() // Save the note's current draft, because the activity is stopping // and we want to be sure the current note progress isn't lost. val values = ContentValues().apply { put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText()) put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle()) } // Do this update in background on an AsyncQueryHandler or equivalent. asyncQueryHandler.startUpdate( token, // int token to correlate calls null, // cookie, not used here uri, // The URI for the note to update. values, // The map of column names and new values to apply to them. null, // No SELECT criteria are used. null // No WHERE columns are used. ) }
Java
@Override protected void onStop() { // Call the superclass method first. super.onStop(); // Save the note's current draft, because the activity is stopping // and we want to be sure the current note progress isn't lost. ContentValues values = new ContentValues(); values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText()); values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle()); // Do this update in background on an AsyncQueryHandler or equivalent. asyncQueryHandler.startUpdate ( mToken, // int token to correlate calls null, // cookie, not used here uri, // The URI for the note to update. values, // The map of column names and new values to apply to them. null, // No SELECT criteria are used. null // No WHERE columns are used. ); }
L'esempio di codice precedente utilizza direttamente SQLite. Tuttavia, ti consigliamo di usare Room, una libreria di persistenza che fornisce un livello di astrazione su SQLite. Per ulteriori informazioni scopri di più sui vantaggi dell'utilizzo di Room e su come implementarla nella tua app vedi il Libreria sulla persistenza della stanza guida.
Quando l'attività passa allo stato Interrotta, Activity
l'oggetto viene mantenuto in memoria: conserva tutti gli stati e
ma non è collegata a Gestione finestre. Quando l'attività
riprendi, richiama queste informazioni.
Non è necessario
reinizializzare i componenti creati durante uno dei metodi di callback
fino allo stato Ripresa. Il sistema tiene traccia anche delle attività
per ogni oggetto View
nel layout, quindi se
l'utente inserisce del testo in un widget EditText
, che
i contenuti vengono conservati, pertanto non è necessario salvarli e ripristinarli.
Nota: una volta interrotta l'attività, il sistema
potrebbe distruggere il processo che contiene l'attività se il sistema
deve recuperare memoria.
Anche se il sistema distrugge il processo mentre l'attività
viene interrotto, il sistema conserva lo stato dell'elemento View
come il testo di un widget EditText
, in un
Bundle
, ossia un blob di coppie chiave/valore, e le ripristina.
se l'utente torna all'attività. Per
per ulteriori informazioni sul ripristino di un'attività a cui un utente ritorna, consulta le
sezione relativa al salvataggio e il ripristino dello stato.
Dallo stato Interrotto, l'attività torna a interagire con
utente o l'attività termina e scompare. Se l'attività si verifica
il sistema richiama onRestart()
.
Se l'esecuzione di Activity
è terminata, il sistema chiama
onDestroy()
.
onDestroy()
onDestroy()
viene chiamato prima di
viene eliminata l'attività. Il sistema richiama questo callback per uno dei due motivi:
-
L'attività è terminata perché l'utente ha ignorato completamente il
per via di un'attività
finish()
in corso ha richiamato l'attività. - Il sistema sta eliminando temporaneamente l'attività a causa di una configurazione come la rotazione del dispositivo o l'attivazione della modalità multi-finestra.
Quando l'attività passa allo stato di eliminazione, qualsiasi componente sensibile al ciclo di vita legato
al ciclo di vita dell'attività riceve
Evento ON_DESTROY
. È qui che entrano in gioco
i componenti del ciclo di vita possono eseguire la pulizia
Eliminazione di Activity
completata.
Invece di inserire la logica in Activity
per determinare perché viene distrutta,
utilizza un oggetto ViewModel
per contenere
pertinenti per Activity
. Se Activity
viene ricreato
a causa di una modifica alla configurazione, ViewModel
non deve fare nulla perché
viene conservato e assegnato alla successiva istanza Activity
.
Se Activity
non viene ricreato, ViewModel
ha
onCleared()
, in cui
può ripulire tutti i dati di cui ha bisogno prima di essere distrutti. Puoi distinguere tra questi due scenari
isFinishing()
.
Se l'attività sta completando, onDestroy()
è il callback finale del ciclo di vita
l'attività ricevuta. Se onDestroy()
viene chiamato come risultato di una configurazione
modificata, il sistema crea immediatamente una nuova istanza di attività e quindi chiama
onCreate()
su quella nuova istanza nella nuova configurazione.
Il callback onDestroy()
rilascia tutte le risorse non svincolate in precedenza
come onStop()
.
Stato dell'attività ed espulsione dalla memoria
Il sistema termina i processi quando ha bisogno di liberare RAM. La probabilità che il sistema l'interruzione di un determinato processo dipende dallo stato del processo al momento. Stato del processo, dipende a sua volta dallo stato dell'attività in esecuzione nel processo. La tabella 1 mostra le correlazioni tra stato del processo, attività e la probabilità che il sistema termini il processo. Questa tabella si applica solo se un processo non esegue altri tipi di componenti dell'applicazione.
Probabilità di essere uccisi | Stato processo | Stato attività finale |
---|---|---|
Minima | In primo piano (avere o per concentrarsi) | Ripristinato |
Bassa | Visibile (senza stato attivo) | Iniziata/in pausa |
Superiore | Sfondo (invisibile) | Interrotto |
Massima | Vuoto | Eliminata |
Tabella 1. Relazione tra ciclo di vita del processo e stato di attività.
Il sistema non interrompe mai direttamente un'attività per liberare memoria. Invece, interrompe il processo in cui viene eseguita l'attività, distruggendo non solo l'attività ma anche tutto ciò che è in esecuzione nel processo. Per scoprire come conservare e ripristinare lo stato dell'interfaccia utente della tua attività quando il processo iniziato dal sistema non si interrompe vedi la sezione relativa al salvataggio e al ripristino dello stato.
L'utente può anche terminare un processo utilizzando Gestione applicazioni, in Impostazioni, per terminare l'app corrispondente.
Per ulteriori informazioni sui processi, vedi Processi e thread Panoramica.
Salvataggio e ripristino dello stato temporaneo della UI
Un utente si aspetta che lo stato UI di un'attività rimanga lo stesso per tutto modifica della configurazione, ad esempio la rotazione o il passaggio alla modalità multi-finestra. Tuttavia, il sistema elimina l'attività per impostazione predefinita quando una configurazione di modifica, cancellando qualsiasi stato della UI memorizzato nell'istanza dell'attività.
Analogamente, un utente si aspetta che lo stato della UI rimanga lo stesso se temporaneamente passare dalla tua app a un'altra app e poi tornare all'app in un secondo momento. Tuttavia, il sistema può eliminare il processo della tua applicazione mentre l'utente è assente e la tua attività viene interrotta.
Quando i vincoli di sistema eliminano l'attività, mantieni
lo stato temporaneo dell'interfaccia utente usando una combinazione
ViewModel
,
onSaveInstanceState()
,
e/o archiviazione locale. Per saperne di più sulle aspettative degli utenti rispetto al sistema
e come conservare al meglio i dati complessi sullo stato dell'UI
da un'attività avviata dal sistema e dall'elaborazione del suo decesso, vedere
Salva gli stati dell'interfaccia utente.
Questa sezione descrive lo stato dell'istanza e come implementare
onSaveInstance()
, che è un callback dell'attività stessa. Se le tue
I dati UI sono leggeri, puoi usare solo onSaveInstance()
per mantenere la UI
lo stato di tutte le modifiche alla configurazione e la morte dei processi avviati dal sistema.
Tuttavia, poiché onSaveInstance()
comporta costi di serializzazione/deserializzazione,
nella maggior parte dei casi utilizzi sia ViewModel
sia onSaveInstance()
,
descritto in
Salva gli stati dell'interfaccia utente.
Nota : per saperne di più sulle modifiche alla configurazione, su come limitare le attività ricreazione, se necessario, e come reagire alle modifiche alla configurazione Visualizza il sistema e Jetpack Compose, dai un'occhiata Pagina Gestisci le modifiche alla configurazione.
Stato istanza
Esistono alcuni scenari in cui la tua attività viene eliminata a causa di una normale app
comportamento dell'utente, ad esempio quando l'utente preme il pulsante Indietro o la tua attività
automaticamente la sua distruzione richiamando il
finish()
.
Quando l'attività viene eliminata perché l'utente preme Indietro
o l'attività termina da sola, il concetto di sistema
che l'istanza Activity
è stata rimossa per sempre. In queste
scenari, le aspettative dell'utente corrispondono al comportamento del sistema e tu non
non devi fare altro.
Tuttavia, se il sistema elimina l'attività a causa di vincoli di sistema (come
alla configurazione o alla pressione della memoria), sebbene l'effettiva
Activity
scompare, il sistema ricorda che esisteva. Se l'utente tenta di
tornando all'attività, il sistema crea una nuova istanza
attività utilizzando un insieme di dati salvati che descrivono lo stato dell'attività
quando è stato distrutto.
I dati salvati che il sistema utilizza per ripristinare
precedente è chiamato stato istanza. È una raccolta
coppie chiave-valore archiviate in un oggetto Bundle
. Per impostazione predefinita,
utilizza lo stato dell'istanza Bundle
per salvare le informazioni
su ogni oggetto View
nel layout delle attività, ad esempio
il valore di testo inserito in un
Widget EditText
.
Quindi, se l'istanza dell'attività viene eliminata e ricreata, lo stato del layout è ripristinato allo stato precedente senza necessità di codice. Tuttavia, potrebbe avere più informazioni sullo stato che vorresti ripristinare, ad esempio che tengono traccia dell'avanzamento dell'utente nell'attività.
Nota : per consentire al sistema Android di ripristinare lo stato di
tutte le visualizzazioni della tua attività, ciascuna di esse deve avere un ID univoco, fornito
l'attributo android:id
.
Un oggetto Bundle
non è appropriato per conservare più di una
trascurabile, perché richiede la serializzazione sul thread principale e consuma
dei processi di sistema. Per conservare più di una piccola quantità di dati,
adottare un approccio combinato alla conservazione dei dati, usando
spazio di archiviazione, il metodo onSaveInstanceState()
e
ViewModel
corso, come descritto in
Salva gli stati dell'interfaccia utente.
Salva stato UI semplice e leggero utilizzando onSaveInstanceState()
Quando l'attività inizia a interrompersi, il sistema chiama la
onSaveInstanceState()
in modo che la tua attività possa salvare le informazioni sullo stato in uno stato di istanza
gruppo. L'implementazione predefinita di questo metodo salva
informazioni sullo stato della gerarchia delle visualizzazioni dell'attività, ad esempio
testo in un widget EditText
o la posizione di scorrimento di
Widget ListView
.
Per salvare ulteriori informazioni sullo stato dell'istanza per la tua attività, esegui l'override
onSaveInstanceState()
e aggiungi coppie chiave-valore all'oggetto Bundle
salvato
nel caso in cui l'attività venga eliminata inaspettatamente. Quando esegui l'override
onSaveInstanceState()
, devi chiamare l'implementazione della superclass
se vuoi che l'implementazione predefinita salvi lo stato della gerarchia delle viste.
Ciò è mostrato nell'esempio seguente:
Kotlin
override fun onSaveInstanceState(outState: Bundle?) { // Save the user's current game state. outState?.run { putInt(STATE_SCORE, currentScore) putInt(STATE_LEVEL, currentLevel) } // Always call the superclass so it can save the view hierarchy state. super.onSaveInstanceState(outState) } companion object { val STATE_SCORE = "playerScore" val STATE_LEVEL = "playerLevel" }
Java
static final String STATE_SCORE = "playerScore"; static final String STATE_LEVEL = "playerLevel"; // ... @Override public void onSaveInstanceState(Bundle savedInstanceState) { // Save the user's current game state. savedInstanceState.putInt(STATE_SCORE, currentScore); savedInstanceState.putInt(STATE_LEVEL, currentLevel); // Always call the superclass so it can save the view hierarchy state. super.onSaveInstanceState(savedInstanceState); }
Nota:
onSaveInstanceState()
non è
chiamato quando l'utente chiude esplicitamente l'attività o, in altri casi, quando
finish()
è stato chiamato.
Per salvare dati permanenti, ad esempio le preferenze utente o i dati per un database,
cogliere le opportunità appropriate quando la tua attività è in primo piano.
Se non si presenta questa opportunità, salva i dati persistenti durante
onStop()
.
Ripristina lo stato della UI dell'attività utilizzando lo stato dell'istanza salvato
Quando la tua attività viene ricreata dopo essere stata eliminata in precedenza,
Puoi recuperare lo stato dell'istanza salvata da Bundle
dal sistema alla tua attività. Entrambi i campi
onCreate()
e
onRestoreInstanceState()
ricevono lo stesso Bundle
che contiene
informazioni sullo stato dell'istanza.
Poiché il metodo onCreate()
è
chiamata se il sistema sta creando una nuova istanza dell'attività
o se ne crei di nuovo uno precedente, devi verificare se lo stato Bundle
è nullo prima di provare a leggerlo. Se è null, il sistema
è la creazione di una nuova istanza dell'attività, invece di ripristinare
quella precedente che era stata distrutta.
Il seguente snippet di codice mostra come ripristinare
dati sullo stato in onCreate()
:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Always call the superclass first // Check whether we're recreating a previously destroyed instance. if (savedInstanceState != null) { with(savedInstanceState) { // Restore value of members from saved state. currentScore = getInt(STATE_SCORE) currentLevel = getInt(STATE_LEVEL) } } else { // Probably initialize members with default values for a new instance. } // ... }
Java
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Always call the superclass first // Check whether we're recreating a previously destroyed instance. if (savedInstanceState != null) { // Restore value of members from saved state. currentScore = savedInstanceState.getInt(STATE_SCORE); currentLevel = savedInstanceState.getInt(STATE_LEVEL); } else { // Probably initialize members with default values for a new instance. } // ... }
Invece di ripristinare lo stato durante
onCreate()
, puoi scegliere di implementare
onRestoreInstanceState()
, che il sistema chiama dopo il
onStart()
. Il sistema chiama
onRestoreInstanceState()
solo se esiste uno stato salvato da ripristinare, quindi
non occorre verificare se Bundle
è nullo.
Kotlin
override fun onRestoreInstanceState(savedInstanceState: Bundle?) { // Always call the superclass so it can restore the view hierarchy. super.onRestoreInstanceState(savedInstanceState) // Restore state members from saved instance. savedInstanceState?.run { currentScore = getInt(STATE_SCORE) currentLevel = getInt(STATE_LEVEL) } }
Java
public void onRestoreInstanceState(Bundle savedInstanceState) { // Always call the superclass so it can restore the view hierarchy. super.onRestoreInstanceState(savedInstanceState); // Restore state members from saved instance. currentScore = savedInstanceState.getInt(STATE_SCORE); currentLevel = savedInstanceState.getInt(STATE_LEVEL); }
Attenzione: chiama sempre l'implementazione superclass
onRestoreInstanceState()
in modo che l'implementazione predefinita possa ripristinare lo stato della gerarchia delle viste.
Spostarsi tra le attività
È probabile che un'app entri e abbandoni un'attività, forse molte volte, durante dell'intera durata dell'app, ad esempio quando l'utente tocca il pulsante Indietro del dispositivo. o l'attività avvia un'altra attività.
Questa sezione tratta gli argomenti che devi conoscere per implementare correttamente le transizioni delle attività. Questi argomenti includono l'avvio di un'attività da un'altra attività, il salvataggio delle attività e ripristinare lo stato dell'attività.
Iniziare un'attività da un'altra
Spesso, un'attività deve iniziare un'altra attività in un determinato momento. Questa esigenza si verifica, ad esempio, quando un'app deve passare dalla schermata corrente a uno nuovo.
A seconda che la tua attività voglia o meno ricevere i risultati dalla nuova attività
stai per iniziare, puoi avviare la nuova attività utilizzando
startActivity()
o il metodo
startActivityForResult()
. In entrambi i casi, passi in un oggetto Intent
.
L'oggetto Intent
specifica l'esatta
l'attività da avviare o descrive il tipo di azione da eseguire.
Il sistema seleziona l'attività appropriata per te, che può anche essere
da un'altra applicazione. Un oggetto Intent
può
contengono anche piccole quantità di dati che possono essere utilizzate dall'attività avviata.
Per ulteriori informazioni sul corso Intent
, vedi
Intenzioni e intenzione
Filtri:
startActivity()
Se non è necessario che l'attività appena avviata restituisca un risultato, l'attività corrente può avviarla.
chiamando il metodo
startActivity()
.
Quando si lavora all'interno di una propria applicazione, spesso è necessario semplicemente avviare un'attività nota.
Ad esempio, il seguente snippet di codice mostra come avviare un'attività denominata
SignInActivity
.
Kotlin
val intent = Intent(this, SignInActivity::class.java) startActivity(intent)
Java
Intent intent = new Intent(this, SignInActivity.class); startActivity(intent);
L'applicazione potrebbe anche voler eseguire alcune azioni, ad esempio inviare un'email SMS o aggiornamento di stato, utilizzando i dati delle tue attività. In questo caso, l'applicazione potrebbe non disporre di attività proprie per eseguire tali azioni. in modo da poter invece sfruttare le attività fornite da altre applicazioni sul dispositivo, può eseguire tali azioni per tuo conto.
È qui che le intenzioni hanno davvero valore. Puoi creare un nuovo intent che descriva un'azione da eseguire e il sistema avvia l'app all'attività di un'altra applicazione. Se più attività possono gestire l'intento, dopodiché potrà selezionare quello da utilizzare. Ad esempio, se vuoi consentire all'utente di inviare un'email, puoi creare il seguente intent:
Kotlin
val intent = Intent(Intent.ACTION_SEND).apply { putExtra(Intent.EXTRA_EMAIL, recipientArray) } startActivity(intent)
Java
Intent intent = new Intent(Intent.ACTION_SEND); intent.putExtra(Intent.EXTRA_EMAIL, recipientArray); startActivity(intent);
L'extra EXTRA_EMAIL
aggiunto all'intent è un array di stringhe di
gli indirizzi email a cui deve essere inviata l'email. Quando un'applicazione email
a questo intent, legge l'array di stringhe fornito
inserisce gli indirizzi nella campo del modulo di composizione dell'email. In questo
inizia l'attività dell'applicazione email e, quando l'utente ha finito,
l'attività riprende.
startActivityForResult()
A volte potresti voler ottenere un risultato da un'attività quando termina. Ad esempio, potresti iniziare
un'attività che consente all'utente di scegliere una persona da un elenco di contatti. Al termine, restituisce
persona selezionata. A questo scopo, devi chiamare il
startActivityForResult(Intent, int)
in cui
il parametro numero intero identifica la chiamata.
Questo identificatore serve a distinguere tra più chiamate a
startActivityForResult(Intent, int)
dalla stessa attività. Non è un identificatore globale
e non rischiano di entrare in conflitto con altre app o attività. Il risultato viene restituito tramite
onActivityResult(int, int, Intent)
.
Quando l'attività secondaria viene chiusa, può chiamare setResult(int)
a
e restituire i dati all'elemento principale.
L'attività figlio deve fornire un codice risultato, che può essere i risultati standard
RESULT_CANCELED
, RESULT_OK
o valori personalizzati
a partire da RESULT_FIRST_USER
.
Inoltre,
l'attività secondaria può restituire facoltativamente un Intent
contenente gli eventuali dati aggiuntivi richiesti. L'attività genitore utilizza
onActivityResult(int, int, Intent)
, insieme all'identificatore intero dell'attività principale originariamente
fornite, per ricevere le informazioni.
Se per qualsiasi motivo l'attività di tuo figlio non va a buon fine, ad esempio un arresto anomalo, il genitore
l'attività riceve un risultato con il codice RESULT_CANCELED
.
Kotlin
class MyActivity : Activity() { // ... override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { // When the user center presses, let them pick a contact. startActivityForResult( Intent(Intent.ACTION_PICK,Uri.parse("content://contacts")), PICK_CONTACT_REQUEST) return true } return false } override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) { when (requestCode) { PICK_CONTACT_REQUEST -> if (resultCode == RESULT_OK) { // A contact was picked. Display it to the user. startActivity(Intent(Intent.ACTION_VIEW, intent?.data)) } } } companion object { internal val PICK_CONTACT_REQUEST = 0 } }
Java
public class MyActivity extends Activity { // ... static final int PICK_CONTACT_REQUEST = 0; public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { // When the user center presses, let them pick a contact. startActivityForResult( new Intent(Intent.ACTION_PICK, new Uri("content://contacts")), PICK_CONTACT_REQUEST); return true; } return false; } protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PICK_CONTACT_REQUEST) { if (resultCode == RESULT_OK) { // A contact was picked. Display it to the user. startActivity(new Intent(Intent.ACTION_VIEW, data)); } } } }
Coordinare le attività
Quando un'attività inizia un'altra, entrambe attraversano il ciclo di vita. La prima attività smette di funzionare e passa allo stato In pausa o Interrotta, mentre l'altra viene creata l'attività. Nel caso in cui queste attività condividano dati salvati su disco o altrove, è importante comprendere che la prima attività non si interrompe completamente prima della seconda viene creato. Piuttosto, il processo per avviare il secondo si sovrappone con il processo di interrompendo la prima.
L'ordine dei callback del ciclo di vita è ben definito, in particolare quando le due attività nello stesso processo, ovvero la stessa app, e uno inizia l'altro. Ecco l'ordine delle operazioni che si verificano quando l'attività A inizia l'attività B:
- Viene eseguito il metodo
onPause()
dell'attività A. onCreate()
dell'attività B,onStart()
e I metodionResume()
vengono eseguiti in sequenza. Ora l'attività B è incentrata sugli utenti.- Se l'attività A non è più visibile sullo schermo, viene eseguito il relativo metodo
onStop()
.
Questa sequenza di callback del ciclo di vita consente di gestire la transizione informazioni da un'attività all'altra.