Quando vengono chiamati esattamente onSaveInstanceState () e onRestoreInstanceState ()?


102

La figura seguente (dal documento ufficiale ) descrive il ben noto ciclo di vita di un'attività Android:

inserisci qui la descrizione dell'immagine

Quando invece l'attività viene distrutta dal sistema (ad esempio perché occorre recuperare la memoria), lo stato dell'attività viene talvolta salvato e ripristinato automaticamente mediante i metodi onSaveInstanceState()e onRestoreInstanceState(), come illustrato dalla figura seguente (anche dal documento ufficiale ):

inserisci qui la descrizione dell'immagine

Sono consapevole che nononSaveInstanceState() viene sempre chiamato quando un'attività sta per essere distrutta. Ad esempio, se viene distrutto perché l'utente ha premuto il pulsante "indietro", lo stato dell'attività non viene conservato. Ma nei casi in cui lo stato viene salvato e ripristinato e onSaveInstanceState()/ onRestoreInstanceState()vengono richiamati, quando vengono richiamati esattamente ?

Ad esempio, secondo le figure precedenti, onRestoreInstanceState()potrebbe essere chiamato prima onStart()o dopo onStart()ma prima onResume()o dopo onResume(). Allo stesso modo, esistono diverse possibilità per onSaveInstanceState(). Quindi quando vengono chiamati esattamente?

Idealmente, quello che vorrei è vedere un diagramma combinato che mostri gli stati del ciclo di vita dell'attività e i metodi di salvataggio / ripristino , se esistenti.


ha ottenuto la risposta finale dal documento ufficiale di Android, onSaveInstanceState () chiamato tra onPause () e onStop ().
Rishi

1
@Rishi Puoi fornire un collegamento a quel documento?
Luis Mendo


leggi qui il paragrafo Salva lo stato dell'attività
Rishi

se ho ragione o no, per favore chiarisci
Rishi

Risposte:


107

Secondo la documentazione :

void onRestoreInstanceState (Bundle savedInstanceState)

Questo metodo viene chiamato tra onStart()e onPostCreate(Bundle).

void onSaveInstanceState (Bundle outState)

Se chiamato, questo metodo si verificherà dopo onStop () per applicazioni destinate a piattaforme che iniziano con Build.VERSION_CODES.P. Per le applicazioni destinate a versioni precedenti della piattaforma, questo metodo verrà eseguito prima di onStop () e non ci sono garanzie sul fatto che accadrà prima o dopo onPause ().


1
Grazie. Potresti fornire i link alla documentazione?
Luis Mendo

Ecco fatto, inoltre non credo ci sia nient'altro tra onStart () e onPostCreate (), quindi onRestoreInstanceState () è ben definito nella catena.
Steve M

Molte grazie. Questo chiarisce la questione
Luis Mendo

1
@SteveM "Non ci sono garanzie sul fatto che accadrà prima o dopo onPause ()" Questo significa che se proviamo ad accedere a una vista (per ottenere un valore da salvare, come un indice da un listview) potremmo incappare in NullPointerExceptions?
Tiago

3
Allora, cosa si consiglia di salvare una struttura dati in onPause e ripristinarla in onResume invece in onSaveInstanceState e onRestoreInstanceState?
Gödel77

18

Come per doc1 e doc2

onSaveInstanceState

Prima di Honeycomb, le attività non erano considerate interrompibili fino a dopo essere state messe in pausa, il che significa che onSaveInstanceState () veniva chiamato immediatamente prima di onPause (). A partire da Honeycomb, tuttavia, le attività sono considerate interrompibili solo dopo essere state interrotte, il che significa che onSaveInstanceState () verrà ora chiamato prima di onStop () invece che immediatamente prima di onPause ().

onRestoreInstanceState

Questo metodo viene chiamato tra onStart () e onPostCreate (Bundle) quando l'attività viene reinizializzata da uno stato precedentemente salvato


mi è piaciuto il modo in cui hai descritto gli scenari su diverse versioni di Android
Jimit Patel

14

Oltre alle risposte già pubblicate, c'è un sottile cambiamento introdotto in Android P, che è:

void onSaveInstanceState (Bundle outState)

Se chiamato, questo metodo si verificherà DOPO onStop() per applicazioni destinate piattaforme che iniziano con P . Per le applicazioni destinate a versioni precedenti della piattaforma, questo metodo verrà applicato prima onStop()e non ci sono garanzie sul fatto che accadrà prima o dopo onPause().

Fonte: documenti

Quanto al motivo per cui è stata introdotta questa modifica, ecco la risposta:

... quindi un'applicazione può eseguire in sicurezza transazioni di frammento onStop()e sarà in grado di salvare lo stato persistente in un secondo momento.

Fonte: documenti


Ciao, ottimo commento. Sai come si comporteranno le app che hanno come target P ma vengono eseguite su API inferiori? Uguale all'app che ha come target un'api inferiore o sarà coerente con l'api e manterrà il comportamento "targeting dell'api"?
Filipkowicz

@Filipkowicz, Do you know how will behave app that target P but runs on lower api?Finché l'app viene eseguita su diciamo M, la versione di Android che questo dispositivo ha non contiene modifiche, che vengono introdotte in P, il che significa che indipendentemente dal target specificato come Pnon vedrai diverso per i dispositivi pre-P. Spero che questo risponda alla tua domanda.
azizbekian

Mi sento così rilassato oggi dopo aver letto questa risposta, perché stavo facendo il corso gratuito per Android su Udacity e hanno ancora la vecchia versione dei tutorial che affermano nell'esercizio 8 della lezione 5 che i metodi onStop e onDestroy non dovrebbero essere presenti nel textView visualizzato. Ma non sapevo che fosse per le versioni precedenti di Android e stavo eseguendo la mia applicazione su Android pie e stavo ottenendo il metodo onStop nel mio textView. Grazie mille. Finalmente mi sento bene.
Sandhu

6

Questa è un'informazione extra per onSaveInstanceState (Bundle)

da documenti

Non confondere questo metodo con i callback del ciclo di vita delle attività come onPause (), che viene sempre chiamato quando un'attività viene posizionata in background o in procinto di essere distrutta, o onStop () che viene chiamato prima della distruzione. Un esempio di quando vengono chiamati onPause () e onStop () e non questo metodo è quando un utente torna dall'attività B all'attività A: non è necessario chiamare onSaveInstanceState (Bundle) su B perché quella particolare istanza non verrà mai ripristinata , quindi il sistema evita di chiamarlo. Un esempio quando viene chiamato onPause () e non onSaveInstanceState (Bundle) è quando l'attività B viene avviata davanti all'attività A: il sistema potrebbe evitare di chiamare onSaveInstanceState (Bundle) sull'attività A se non viene ucciso durante la durata di B da allora lo stato dell'interfaccia utente di A rimarrà intatto.

Quindi è l'implementazione predefinita per ..

L'implementazione predefinita si prende cura della maggior parte dello stato dell'interfaccia utente per istanza chiamando onSaveInstanceState () su ogni vista nella gerarchia che ha un id e salvando l'id della vista attualmente focalizzata (tutto ripristinato dal implementazione predefinita di onRestoreInstanceState (Bundle)). Se sovrascrivi questo metodo per salvare informazioni aggiuntive non acquisite da ogni singola visualizzazione, probabilmente vorrai chiamare l'implementazione predefinita, altrimenti preparati a salvare tu stesso tutto lo stato di ciascuna visualizzazione.


0
String activityState;
@Override 
public void onCreate(Bundle savedInstanceState) {
// call the super class onCreate to complete the creation of activity like 
// the view hierarchy 
super.onCreate(savedInstanceState);

// recovering the instance state 
if (savedInstanceState != null) {
     activityState = savedInstanceState.getString(STATE_KEY);
 } 

   setContentView(R.layout.main_activity);
   mTextView = (TextView) findViewById(R.id.text_view);
} 

// Questo callback viene chiamato solo quando è presente un'istanza salvata precedentemente salvata utilizzando // onSaveInstanceState (). Ripristiniamo uno stato in onCreate () mentre possiamo facoltativamente ripristinare // un altro stato qui, eventualmente utilizzabile dopo che onStart () è stato completato. // Il pacchetto savedInstanceState è uguale a quello utilizzato in onCreate ().

@Override 
public void onRestoreInstanceState(Bundle savedInstanceState) {
 mTextView.setText(savedInstanceState.getString(STATE_KEY));
  } 


// invoked when the activity may be temporarily destroyed, save the instance 
//state here 
//this method will be called before onstop

@Override 
 public void onSaveInstanceState(Bundle outState) {
    outState.putString(STATE_KEY, activityState);

    // call superclass to save any view hierarchy 
    super.onSaveInstanceState(outState);
} 

Mi scusi, come risponde questo alla domanda quando vengono chiamati esattamente i metodi di salvataggio / ripristino ?
Luis Mendo
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.