Diverse operazioni del sistema Android possono influire sullo stato del frammento. Per garantire che lo stato dell'utente venga salvato, il framework Android salva e ripristina automaticamente i frammenti e lo stack di back. Pertanto, devi assicurarti che anche tutti i dati nel frammento vengano salvati e ripristinati.
La tabella seguente illustra le operazioni che causano la perdita di stato del frammento e indica se i vari tipi di stato persistono anche dopo aver apportato queste modifiche. I tipi di stato menzionati nella tabella sono i seguenti:
- Variabili: variabili locali nel frammento.
- Stato visualizzazione: tutti i dati di proprietà di una o più viste nel frammento.
- SalvatoState: dati inerenti a questa istanza del frammento che devono essere salvati in
onSaveInstanceState()
. - NonConfig: dati estratti da un'origine esterna, ad esempio un server o un repository locale, oppure dati creati dall'utente che vengono inviati a un server dopo il commit.
Spesso le variabili vengono trattate come SalvaState, ma la seguente tabella distingue le due cose per dimostrare l'effetto delle varie operazioni su ognuna.
Funzionamento | Variabili | Stato visualizzazione | StatoSalvato | Non configurazione |
---|---|---|---|---|
Aggiunto allo stack precedente | ✓ | ✓ | x | ✓ |
Modifica della configurazione | x | ✓ | ✓ | ✓ |
Processo di morte/ricreazione | x | ✓ | ✓ | ✓* |
Rimossa non aggiunta allo stack posteriore | x | x | x | x |
Host terminato | x | x | x | x |
* Lo stato NonConfig può essere mantenuto dopo l'interruzione del processo utilizzando il modulo Stato salvato per ViewModel.
Tabella 1: varie operazioni distruttive relative ai frammenti e relativi effetti su diversi tipi di stato.
Vediamo un esempio specifico. Prendiamo in considerazione una schermata che genera una stringa casuale, la visualizza in un TextView
e offre un'opzione per modificare la stringa prima di inviarla a un amico:
In questo esempio, supponiamo che, dopo che l'utente preme il pulsante di modifica, l'app mostri una vista EditText
in cui l'utente può modificare il messaggio. Se l'utente fa clic su ANNULLA, la visualizzazione EditText
deve essere cancellata e la visibilità è impostata su View.GONE
. Una schermata di questo tipo potrebbe richiedere la gestione di quattro tipi di dati per garantire un'esperienza senza interruzioni:
Dati | Tipo | Tipo di stato | Descrizione |
---|---|---|---|
seed |
Long |
Non configurazione | Seme utilizzato per generare casualmente una nuova buona azione. Viene generato quando viene creato il campo ViewModel . |
randomGoodDeed |
String |
SaveState + Variabile | Generato quando il frammento viene creato per la prima volta.
randomGoodDeed viene salvato per garantire che gli utenti vedano le stesse azioni casuali anche dopo la morte e la ricreazione del processo. |
isEditing |
Boolean |
SaveState + Variabile | Contrassegno booleano impostato su true quando l'utente inizia la modifica.
isEditing viene salvato per garantire che la parte di modifica dello schermo rimanga visibile quando il frammento viene ricreato. |
Testo modificato | Editable |
Visualizza stato (di proprietà di EditText ) |
Il testo modificato nella visualizzazione EditText .
La visualizzazione EditText salva questo testo per garantire che le modifiche in corso
dell'utente non vadano perse. |
Tabella 2: indica che deve essere gestita dall'app di generazione di testo casuale.
Le seguenti sezioni descrivono come gestire correttamente lo stato dei dati tramite operazioni distruttive.
Visualizza stato
Le viste sono responsabili della gestione del proprio stato. Ad esempio, quando una vista accetta l'input utente, è responsabilità della vista salvare e ripristinare l'input per gestire le modifiche alla configurazione. Tutte le viste fornite dal framework Android
hanno la propria implementazione di onSaveInstanceState()
e
onRestoreInstanceState()
, quindi non è necessario gestire lo stato di visualizzazione all'interno
del frammento.
Ad esempio, nello scenario precedente, la stringa modificata viene archiviata in un elemento EditText
. Un EditText
conosce il valore del testo visualizzato e altri dettagli, come l'inizio e la fine di qualsiasi testo selezionato.
Una vista richiede un ID per mantenere il proprio stato. Questo ID deve essere univoco all'interno del frammento e nella relativa gerarchia delle visualizzazioni. Le visualizzazioni senza un ID non possono mantenere il loro stato.
<EditText android:id="@+id/good_deed_edit_text" android:layout_width="match_parent" android:layout_height="wrap_content" />
Come indicato nella tabella 1, le viste salvano e ripristinano il proprio ViewState
tramite tutte le operazioni che non rimuovono il frammento o eliminano l'host.
SavedState
Il frammento è responsabile della gestione di piccole quantità di stato dinamico
che sono parte integrante del funzionamento del frammento. Puoi conservare i dati facilmente serializzati utilizzando Fragment.onSaveInstanceState(Bundle)
.
Come per
Activity.onSaveInstanceState(Bundle)
,
i dati inseriti nel bundle vengono conservati attraverso modifiche alla configurazione
ed eliminazione e ricreazione dei processi e sono disponibili nei metodi
onCreate(Bundle)
,
onCreateView(LayoutInflater, ViewGroup, Bundle)
e
onViewCreated(View, Bundle)
del frammento.
Continuando con l'esempio precedente, randomGoodDeed
è l'atto mostrato all'utente, mentre isEditing
è un flag per determinare se il frammento mostra o nasconde EditText
. Questo stato salvato deve essere mantenuto utilizzando onSaveInstanceState(Bundle)
, come mostrato nell'esempio seguente:
Kotlin
override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putBoolean(IS_EDITING_KEY, isEditing) outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed) }
Java
@Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean(IS_EDITING_KEY, isEditing); outState.putString(RANDOM_GOOD_DEED_KEY, randomGoodDeed); }
Per ripristinare lo stato in onCreate(Bundle)
, recupera il valore archiviato dal bundle:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) isEditing = savedInstanceState?.getBoolean(IS_EDITING_KEY, false) randomGoodDeed = savedInstanceState?.getString(RANDOM_GOOD_DEED_KEY) ?: viewModel.generateRandomGoodDeed() }
Java
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { isEditing = savedInstanceState.getBoolean(IS_EDITING_KEY, false); randomGoodDeed = savedInstanceState.getString(RANDOM_GOOD_DEED_KEY); } else { randomGoodDeed = viewModel.generateRandomGoodDeed(); } }
Come indicato nella tabella 1, tieni presente che le variabili vengono conservate quando il frammento viene posizionato nel backstack. Trattarli come stati salvati garantisce che permangano in tutte le operazioni distruttive.
Non configurazione
I dati NonConfig devono essere posizionati all'esterno del frammento, ad esempio in una ViewModel
. Nell'esempio precedente riportato sopra, seed
(il nostro stato NonConfig) viene generato in ViewModel
.
La logica per mantenere il proprio stato è di proprietà di ViewModel
.
Kotlin
public class RandomGoodDeedViewModel : ViewModel() { private val seed = ... // Generate the seed private fun generateRandomGoodDeed(): String { val goodDeed = ... // Generate a random good deed using the seed return goodDeed } }
Java
public class RandomGoodDeedViewModel extends ViewModel { private Long seed = ... // Generate the seed private String generateRandomGoodDeed() { String goodDeed = ... // Generate a random good deed using the seed return goodDeed; } }
La classe ViewModel
consente intrinsecamente che i dati sopravvivono alle modifiche alla configurazione, come le rotazioni dello schermo, e rimangono in memoria quando il frammento viene inserito nello stack posteriore. Dopo la morte e la ricreazione del processo,
il ViewModel
viene ricreato e viene generato un nuovo seed
. L'aggiunta di un modulo SavedState
a ViewModel
consente a ViewModel
di mantenere lo stato semplice attraverso processi di morte e attività ricreative.
Risorse aggiuntive
Per ulteriori informazioni sulla gestione dello stato dei frammenti, consulta le seguenti risorse aggiuntive.
Codelab
- Codelab sui componenti sensibili al ciclo di vita