Alcune configurazioni dei dispositivi possono cambiare mentre l'app è in esecuzione. Queste includono, a titolo esemplificativo:
- Dimensioni di visualizzazione dell'app
- Orientamento schermo
- Dimensioni e spessore del carattere
- Impostazioni internazionali
- Modalità Buio e modalità Luce
- Disponibilità della tastiera
La maggior parte di queste modifiche alla configurazione si verifica a causa di un'interazione dell'utente. Ad
esempio, la rotazione o la chiusura del dispositivo modifica la quantità di spazio sullo schermo
disponibile per l'app. Allo stesso modo, la modifica delle impostazioni del dispositivo, come le dimensioni del carattere,
la lingua o il tema preferito, modifica i rispettivi valori nell'
Configuration oggetto.
Questi parametri in genere richiedono modifiche sufficientemente grandi all'interfaccia utente dell'applicazione, tanto che la piattaforma Android ha un meccanismo appositamente creato per quando cambiano.
Questo meccanismo è la ricreazione dell'Activity.
Ricreazione dell'attività
Il sistema ricrea un Activity quando si verifica una modifica alla configurazione. A questo scopo, il sistema chiama onDestroy ed elimina l'istanza Activity
esistente. Poi crea una nuova istanza utilizzando onCreate, che viene inizializzata con la nuova
Activity configurazione aggiornata. Ciò significa anche che il sistema ricrea l'interfaccia utente con la nuova configurazione.
In genere, l'Activity funge da host per i componibili. Quando l'Activity viene ricreata, Compose ricrea anche l'interfaccia utente utilizzando i nuovi valori di configurazione.
Il comportamento di ricreazione aiuta l'applicazione ad adattarsi alle nuove configurazioni ricaricando automaticamente l'applicazione con risorse alternative che corrispondono alla nuova configurazione del dispositivo.
Esempio di ricreazione
Considera un componibile che visualizza un titolo statico utilizzando una risorsa stringa:
// In the res/values/strings.xml file // <string name="compose">Jetpack Compose</string> // In your Compose code Text( text = stringResource(R.string.compose) )
Quando viene creata l'Activity, il componibile Text legge la configurazione corrente (ad esempio la lingua) e risolve la risorsa stringa appropriata.
Se la lingua cambia, il sistema ricrea l'attività. In questo caso, Compose ricrea l'interfaccia utente. Poiché stringResource legge dalla configurazione corrente, il titolo viene aggiornato automaticamente al valore localizzato corretto.
La ricreazione cancella anche qualsiasi stato mantenuto come campi nell'Activity.
Per conservare lo stato dell'interfaccia utente durante le modifiche alla configurazione, utilizza i pattern di gestione dello stato consigliati. Utilizza ViewModel per i dati e la logica di business e rememberSaveable per lo stato a livello di UI. Con questi meccanismi, lo stato sopravvive alla ricreazione dell'Activity, mentre l'interfaccia utente viene aggiornata per riflettere la nuova configurazione.
Per saperne di più sul salvataggio dello stato in Compose, consulta Salvare lo stato dell'interfaccia utente in Compose.
Aspettative degli utenti
L'utente di un'app si aspetta che lo stato venga conservato. Se un utente sta compilando un modulo e apre un'altra app in modalità multi-finestra per consultare le informazioni, l'esperienza utente è negativa se torna a un modulo vuoto o a un'altra parte dell'app. In qualità di sviluppatore, devi fornire un'esperienza utente coerente durante le modifiche alla configurazione e la ricreazione dell'attività.
Per verificare se lo stato viene conservato nella tua applicazione, puoi eseguire azioni che causano modifiche alla configurazione sia quando l'app è in primo piano sia quando è in background. Queste azioni includono:
- Ruotare il dispositivo
- Attivare la modalità multi-finestra
- Ridimensionare l'applicazione in modalità multi-finestra o in una finestra in formato libero
- Chiudere un dispositivo pieghevole con più display
- Modificare il tema del sistema, ad esempio la modalità Buio e la modalità Luce
- Modificare le dimensioni del carattere
- Modificare la lingua del sistema o dell'app
- Collegare o scollegare una tastiera hardware
- Collegare o scollegare una docking station
Esistono diversi approcci che puoi adottare per conservare lo stato pertinente durante la ricreazione dell'Activity. La scelta dipende dal tipo di stato che vuoi conservare:
- Persistenza locale per gestire l'interruzione del processo per dati complessi o di grandi dimensioni.
Lo spazio di archiviazione locale permanente include database o
DataStore. - Oggetti mantenuti, come le istanze
ViewModel, per gestire lo stato relativo all'interfaccia utente in memoria mentre l'utente utilizza attivamente l'app. rememberSaveableper conservare lo stato dell'interfaccia utente temporaneo durante le modifiche alla configurazione e l'interruzione del processo avviata dal sistema. Questa opzione è appropriata per lo stato che dipende dall'input dell'utente, dalla posizione di scorrimento o dalla navigazione, ma non appartiene a unViewModel.
Per leggere informazioni dettagliate sulle API per ciascuna di queste opzioni, e su quando è appropriato utilizzarle, consulta Salvare gli stati dell'interfaccia utente.
Limitare la ricreazione dell'attività
Puoi impedire la ricreazione automatica dell'attività per alcune modifiche alla configurazione. Nelle moderne app solo Compose, l'interfaccia utente viene ricomposta in entrambi i casi, ma è consigliabile gestire direttamente la modifica alla configurazione.
Per impostazione predefinita, una modifica alla configurazione costringe il sistema a eliminare e ricreare l'attività, inclusa l'interfaccia utente e tutti gli oggetti derivati dall'attività. Se dichiari che l'attività gestisce autonomamente la modifica alla configurazione, il sistema impedisce questa operazione. Invece, viene aggiornato solo l'oggetto Configuration e Compose ricompone l'interfaccia utente con i nuovi valori.
La gestione diretta delle modifiche alla configurazione in Compose offre diversi vantaggi:
- Miglioramento del rendimento: la ricomposizione dell'interfaccia utente è meno costosa di un ciclo completo di ricreazione dell'attività, soprattutto per le modifiche minori.
- Animazioni fluide: evitare il riavvio di un'attività consente di eseguire animazioni continue durante le modifiche alla configurazione, ad esempio transizioni di layout fluide durante la rotazione del dispositivo.
- Conservazione dello stato: il mantenimento dell'istanza dell'attività riduce il rischio di perdita dello stato dell'interfaccia utente temporaneo durante un evento come la rotazione dello schermo. Tieni presente che devi comunque gestire la conservazione dello stato per l'interruzione del processo avviata dal sistema.
Per disattivare la ricreazione dell'attività per modifiche alla configurazione specifiche,
aggiungi il tipo di configurazione a android:configChanges nella
<activity> voce del file AndroidManifest.xml. I valori possibili
sono riportati nella documentazione dell'attributo android:configChanges.
Il seguente codice del manifest disattiva la ricreazione per Activity quando
cambiano l'orientamento dello schermo e la disponibilità della tastiera:MyActivity
<activity
android:name=".MyActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:label="@string/app_name">
Android 17
A partire da Android 17 (livello API 37), il sistema non riavvia più le attività per impostazione predefinita per diverse modifiche alla configurazione che in genere non richiedono la ricreazione completa dell'interfaccia utente.
Le attività rimangono attive e ricevono aggiornamenti tramite il
onConfigurationChanged() callback.
Le modifiche alla configurazione specifiche includono:
CONFIG_KEYBOARDCONFIG_KEYBOARD_HIDDENCONFIG_NAVIGATIONCONFIG_TOUCHSCREENCONFIG_COLOR_MODECONFIG_UI_MODE(solo quando la modalità UI cambia inUI_MODE_TYPE_DESKo daUI_MODE_TYPE_DESKa un altro tipo)
Se la tua applicazione si basa su un riavvio completo per ricaricare le risorse per queste
modifiche, ora devi attivare esplicitamente il comportamento precedente utilizzando l'attributo
android:recreateOnConfigChanges nel file manifest.
L'attributo consente di specificare quali modifiche alla configurazione devono attivare un ciclo completo di arresto, eliminazione e ricreazione dell'attività, ad esempio:
<activity
android:name=".MyActivity"
android:recreateOnConfigChanges="keyboard|keyboardHidden|navigation|colorMode|touchscreen|...">
...
</activity>
Reagire alle modifiche alla configurazione
Jetpack Compose consente alla tua app di reagire più facilmente alle modifiche alla configurazione.
Tuttavia, se disattivi la ricreazione dell'Activity per tutte le modifiche alla configurazione in cui è possibile farlo, l'app deve comunque gestire correttamente le modifiche alla configurazione.
L'Configuration oggetto è disponibile nella gerarchia dell'interfaccia utente di Compose con
la composizione locale LocalConfiguration. Ogni volta che cambia, le funzioni componibili che leggono da LocalConfiguration.current vengono ricomposte. Per
informazioni sul funzionamento delle composizioni locali, consulta Dati con ambito locale
con CompositionLocal.
Esempio
Nell'esempio seguente, un componibile visualizza una data con un formato specifico.
Il componibile reagisce alle modifiche alla configurazione delle impostazioni internazionali del sistema chiamando
ConfigurationCompat.getLocales con LocalConfiguration.current.
@Composable
fun DateText(year: Int, dayOfYear: Int) {
val dateTimeFormatter = DateTimeFormatter.ofPattern(
"MMM dd",
ConfigurationCompat.getLocales(LocalConfiguration.current)[0]
)
Text(
dateTimeFormatter.format(LocalDate.ofYearDay(year, dayOfYear))
)
}
Per evitare la ricreazione dell'Activity quando cambiano le impostazioni internazionali, l'Activity che ospita il codice Compose deve disattivare le modifiche alla configurazione delle impostazioni internazionali. Per farlo, imposta android:configChanges su locale|layoutDirection.
Modifiche alla configurazione: concetti chiave e best practice
Ecco i concetti chiave che devi conoscere quando lavori sulle modifiche alla configurazione:
- Configurazioni: le configurazioni dei dispositivi definiscono la modalità di visualizzazione dell'interfaccia utente per l'utente, ad esempio le dimensioni di visualizzazione dell'app, le impostazioni internazionali o il tema del sistema. In Compose, puoi accedere ai valori di configurazione utilizzando
LocalConfiguration. - Modifiche alla configurazione: le configurazioni cambiano tramite l'interazione dell'utente. Ad esempio, l'utente potrebbe modificare le impostazioni del dispositivo o il modo in cui interagisce fisicamente con il dispositivo. Non è possibile impedire le modifiche alla configurazione.
- Ricreazione dell'
Activity: per impostazione predefinita, le modifiche alla configurazione comportano la ricreazione dell'Activity. Si tratta di un meccanismo integrato per reinizializzare lo stato dell'app per la nuova configurazione. - Eliminazione dell'
Activity: la ricreazione dell'Activityfa sì che il sistema elimini la vecchia istanza dell'Activitye ne crei una nuova al suo posto. La vecchia istanza è ora obsoleta. Evita di conservare i riferimenti agli oggetti con ambito del ciclo di vita oltre l'ambito previsto. - Stato: lo stato della vecchia istanza dell'
Activitynon è presente nella nuova istanza dell'Activity, perché si tratta di due istanze di oggetti diversi. Anziché associare lo stato all'attività, utilizza le API consigliate per conservare lo stato dell'app e dell'utente come descritto in Salvare gli stati dell'interfaccia utente. - Disattivazione: la disattivazione della ricreazione dell'attività per un tipo di modifica alla configurazione richiede che l'app venga aggiornata correttamente in reazione alla nuova configurazione.
Per offrire una buona esperienza utente, segui queste best practice:
- Preparati a modifiche frequenti alla configurazione: non dare per scontato che le modifiche alla configurazione siano rare o non si verifichino mai, indipendentemente dal livello API, dal fattore di forma o dal toolkit dell'interfaccia utente. Quando un utente causa una modifica alla configurazione, si aspetta che le app vengano aggiornate e continuino a funzionare correttamente con la nuova configurazione.
- Conserva lo stato: non perdere lo stato dell'utente quando si verifica la ricreazione dell'
Activity. Conserva lo stato come descritto in Salvare gli stati dell'interfaccia utente utilizzando API comeViewModelerememberSaveable. - Evita di disattivare come soluzione rapida: non disattivare la ricreazione dell'
Activitycome scorciatoia per evitare la perdita di stato. La disattivazione della ricreazione dell'attività richiede di rispettare la promessa di gestire la modifica e puoi comunque perdere lo stato a causa della ricreazione dell'Activityda altre modifiche alla configurazione, dalla chiusura del processo o dalla chiusura dell'app. È impossibile disattivare completamente la ricreazione dell'Activity. Conserva lo stato come descritto in Salvare gli stati dell'interfaccia utente. - Non evitare le modifiche alla configurazione: non imporre limitazioni all'orientamento,
alle proporzioni o alla ridimensionabilità per evitare modifiche alla configurazione e
Activityricreazione. Ciò influisce negativamente sugli utenti che vogliono utilizzare la tua app nel modo che preferiscono.
Gestire le modifiche alla configurazione in base alle dimensioni
Le modifiche alla configurazione in base alle dimensioni possono verificarsi in qualsiasi momento e sono più probabili quando l'app viene eseguita su un dispositivo con schermo di grandi dimensioni in cui gli utenti possono attivare la modalità multi-finestra. Si aspettano che l'app funzioni bene in questo ambiente.
Esistono due tipi generali di modifiche alle dimensioni: significative e non significative. Una modifica alle dimensioni significativa è quella in cui un insieme diverso di risorse alternative si applica alla nuova configurazione a causa di una differenza nelle dimensioni dello schermo, ad esempio larghezza, altezza o larghezza minima. Queste risorse includono quelle definite dall'app stessa e quelle di una delle sue librerie.
Limitare la ricreazione dell'attività per le modifiche alla configurazione in base alle dimensioni
Quando disattivi la ricreazione dell'Activity per le modifiche alla configurazione in base alle dimensioni, il sistema non ricrea l'Activity. Riceve invece una chiamata a
Activity.onConfigurationChanged. Tutti i componibili che leggono LocalConfiguration.current vengono ricomposti automaticamente per riflettere le nuove dimensioni.
La ricreazione di Activity è disattivata per le modifiche alla configurazione in base alle dimensioni quando
nel file manifest è presente
android:configChanges="screenSize|smallestScreenSize|orientation|screenLayout".
Risorse aggiuntive
Per saperne di più sulla gestione delle modifiche alla configurazione, consulta le seguenti risorse aggiuntive: