State Restoration è un meccanismo dei sistemi operativi mobili che consente di salvare e ripristinare l'interfaccia utente dell'applicazione dopo il suo riavvio o riduzione a icona. Il sistema salva lo stato dell'interfaccia utente in memoria o in un archivio persistente e lo ripristina alla riapertura. Secondo Android Developers (2025), State Restoration è obbligatorio per le applicazioni che mirano a un'esperienza utente di qualità. State Restoration è fondamentale per prevenire la perdita di dati quando un'applicazione termina inaspettatamente.
Punti chiave
State Restoration (ripristino dello stato) è un meccanismo di sistema che consente di salvare lo stato corrente dell'interfaccia utente dell'applicazione e ripristinarlo dopo la chiusura o il riavvio. Quando un utente riduce a icona un'applicazione o il sistema la chiude per liberare risorse, State Restoration cattura i parametri chiave dell'interfaccia utente e li salva in un archivio crittografato.
Senza State Restoration, gli utenti perdono tutti i dati non salvati quando passano da un'applicazione all'altra. Ad esempio, un modulo di feedback compilato, una lunga query di ricerca o un elenco di notizie visualizzato parzialmente — tutto scompare al riavvio. State Restoration risolve questo problema catturando automaticamente lo stato del ViewController o dell'Activity al momento della riduzione a icona.
Il meccanismo funziona a livello di sistema ed è supportato da entrambe le principali piattaforme mobili. iOS fornisce State Restoration tramite NSUserActivity e il protocollo UIStateRestoring, mentre Android lo fornisce tramite SavedStateHandle nei componenti architetturali Jetpack e ViewModel. L'implementazione differisce, ma il concetto è identico.
Il processo di State Restoration è suddiviso in due fasi: salvataggio e ripristino. Nella fase di salvataggio, il sistema chiama i corrispondenti metodi del ciclo di vita, in cui l'applicazione deve serializzare lo stato corrente dell'interfaccia utente in una rappresentazione compatta. Nella fase di ripristino, il sistema restituisce i dati salvati e l'applicazione li deserializza per ripristinare l'interfaccia utente.
Il salvataggio viene avviato dal sistema quando l'applicazione passa in background o riceve un segnale di chiusura imminente. Su iOS viene chiamato il metodo encodeRestorableState di UIViewController; su Android viene chiamato onSaveInstanceState dell'Activity o il salvataggio tramite SavedStateHandle. I dati vengono serializzati in un formato che supporta i tipi primitivi: stringhe, numeri, array di byte e oggetti Parcelable.
La quantità di dati salvati deve essere minima — il sistema impone limiti sulla dimensione del pacchetto di stato salvato. Su Android, il limite è di circa 50 KB per processo. Il superamento del limite causa un'eccezione TransactionTooLargeException. Pertanto, gli architetti raccomandano di salvare solo identificatori e chiavi e di caricare i dati completi dall'archivio persistente al ripristino.
Durante il ripristino, il sistema passa il pacchetto di dati salvati all'applicazione al momento dell'avvio. Su iOS viene chiamato il metodo decodeRestorableState; su Android viene utilizzato onRestoreInstanceState o la lettura da SavedStateHandle. L'applicazione estrae identificatori e chiavi dal pacchetto e ripristina l'interfaccia utente: posizione di scorrimento, elementi selezionati, dati inseriti.
È importante notare che il ripristino può avvenire in un nuovo processo. Se l'applicazione è stata completamente scaricata dalla memoria, il processo viene creato di nuovo e tutti gli oggetti in memoria sono assenti. Pertanto, lo stato deve essere serializzabile e indipendente dal contesto di esecuzione della sessione precedente. Ciò è particolarmente critico per i moduli grandi con più campi di input e le interfacce lunghe multipagina.
class MainActivity : AppCompatActivity() {
private var searchQuery: String = ""
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("search_query", searchQuery)
}
override fun onRestoreInstanceState(savedState: Bundle) {
super.onRestoreInstanceState(savedState)
searchQuery = savedState.getString("search_query", "")!!
restoreSearchUI(searchQuery)
}
}
L'implementazione di State Restoration differisce significativamente tra le piattaforme. iOS utilizza un approccio dichiarativo tramite storyboard e protocolli UIKit, mentre Android utilizza un approccio imperativo tramite i metodi del ciclo di vita dell'Activity e i componenti architetturali Jetpack. La scelta dell'approccio dipende dalla piattaforma di destinazione e dall'architettura dell'applicazione.
Su iOS, State Restoration si basa su tre componenti: UIApplication gestisce il processo generale, UIViewController implementa il protocollo UIStateRestoring e NSUserActivity memorizza i dati per il ripristino della navigazione. Per abilitarlo, è necessario impostare restorationIdentifier su UIViewController e implementare encodeRestorableState e decodeRestorableState.
iOS salva automaticamente lo stato del controller di navigazione (UINavigationController) e di tutti i ViewController annidati se hanno un restorationIdentifier impostato. Il sistema gestisce lo stack di navigazione e lo ripristina allo stato originale. Tuttavia, i dati all'interno dei controller (testo inserito, posizione di scorrimento) devono essere esplicitamente salvati dallo sviluppatore.
Su Android, l'approccio moderno a State Restoration si basa su SavedStateHandle — un componente della libreria AndroidX Lifecycle. SavedStateHandle è accessibile all'interno di ViewModel e salva e ripristina automaticamente i dati in caso di modifiche alla configurazione (rotazione dello schermo) e riavvio del processo. I dati vengono memorizzati in un Bundle e serializzati automaticamente.
SavedStateHandle si comporta come un archivio chiave-valore con supporto LiveData. In caso di modifiche alla configurazione, i dati vengono salvati e ripristinati automaticamente. Per supportare il riavvio del processo, il ViewModel deve essere creato tramite SavedStateViewModelFactory — ciò consente al ViewModel di sopravvivere alla chiusura completa dell'applicazione.
class SearchViewModel(
private val savedStateHandle: SavedStateHandle
) : ViewModel() {
companion object {
private val KEY_QUERY = string("search_query")
}
fun getSearchQuery(): String? = savedStateHandle[KEY_QUERY]
fun saveSearchQuery(query: String) {
savedStateHandle[KEY_QUERY] = query
}
}
L'implementazione pratica di State Restoration richiede la considerazione di diversi aspetti: scegliere l'archivio giusto, determinare la quantità di dati da salvare e testare vari scenari di chiusura. Esaminiamo un'implementazione passo-passo per un'applicazione Flutter utilizzando il pacchetto state_restoration.
class RestorableSearchField extends RestorableProperty<String> {
String _value = '';
@override
String get value => _value;
@override
void set value(String newValue) {
if (_value != newValue) {
_value = newValue;
notifyListeners();
}
}
@override
String? toPrimitives() => _value;
@override
void fromPrimitives(String? data) {
_value = data ?? '';
}
}
Durante l'implementazione, è importante ricordare i limiti di salvataggio. Non tutti i campi dell'interfaccia utente devono essere ripristinati. Una posizione di scorrimento in un lungo elenco — sì. Uno stato di animazione temporanea — no. Lo sviluppatore deve scegliere consapevolmente quali dati sono critici per l'esperienza utente e quali possono essere reimpostati in sicurezza senza perdita di comodità.
Testare State Restoration è un'attività separata che richiede la simulazione della chiusura del processo. Su Android, ciò può essere fatto tramite il comando adb shell am kill; su iOS, tramite la simulazione di chiusura in Xcode. I framework di test dell'interfaccia utente, come Espresso e XCTest, forniscono metodi speciali per verificare il ripristino dello stato.
La prima regola — salva identificatori, non dati. Invece di salvare l'oggetto completo con cento campi, salva il suo identificatore univoco e, al ripristino, carica i dati effettivi dal database o dall'API. Questo risparmia spazio nel Bundle e garantisce la freschezza dei dati al momento del ripristino.
La seconda regola — testa tutti gli scenari. Verifica il ripristino dopo la rotazione dello schermo, dopo la riduzione a icona e il ritorno un'ora dopo, dopo che il sistema ha chiuso l'applicazione per mancanza di memoria. Ogni scenario può comportarsi diversamente a seconda dello stato del sistema operativo e delle risorse disponibili.
La terza regola — utilizza meccanismi di sistema, non personalizzati. iOS e Android forniscono API integrate per State Restoration ottimizzate per la loro piattaforma specifica. Un'implementazione personalizzata tramite SharedPreferences o UserDefaults può causare problemi di sincronizzazione e comportamenti imprevisti durante il ripristino.
La quarta regola — gestisci l'assenza di stato. Al primo avvio o dopo la cancellazione dei dati, lo stato potrebbe essere assente. L'interfaccia utente deve funzionare correttamente nello stato iniziale senza generare eccezioni. Controlla tutti i dati salvati per null prima dell'uso e fornisci valori predefiniti.
La quinta regola — documenta le chiavi salvate. Quando un progetto ha decine di schermate e ciascuna salva diversi campi, senza una gestione centralizzata delle chiavi si crea caos. Crea una singola classe o file con costanti di chiave per State Restoration in ogni modulo. Questo semplifica la manutenzione e previene la sovrascrittura accidentale dei dati durante il refactoring.
Domande frequenti
State Restoration è un meccanismo per salvare e ripristinare l'interfaccia utente dell'applicazione dopo il riavvio o la riduzione a icona, prevenendo la perdita di dati e contesto dell'utente.
State Restoration salva lo stato temporaneo dell'interfaccia utente (posizione di scorrimento, dati del modulo), mentre un database memorizza i dati persistenti dell'utente. State Restoration utilizza meccanismi di sistema (Bundle, NSData) con limitazioni di volume.
Utilizza SavedStateHandle nel ViewModel di AndroidX Lifecycle. Salva automaticamente i dati durante la riduzione a icona e li ripristina al ritorno. Per il supporto completo al riavvio, utilizza SavedStateViewModelFactory.
Imposta restorationIdentifier su UIViewController e implementa i metodi encodeRestorableState e decodeRestorableState. Per la navigazione, utilizza NSUserActivity con conservazione del percorso nello stack dei controller.
Salva identificatori, non dati completi: ID dell'elemento selezionato, query di ricerca, posizione di scorrimento, stati degli interruttori. Evita di salvare oggetti grandi e immagini.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche