Lifecycle in Jetpack Compose Parte di Android Jetpack.
I componenti sensibili al ciclo di vita eseguono azioni in risposta a una modifica dello stato del ciclo di vita dell'attività host. L'artefatto
androidx.lifecycle.compose
fornisce API dedicate che liberano spazio automaticamente dalle risorse quando escono dallo schermo o quando l'applicazione va in background.
Le API principali includono:
- Flussi per l'attuale
Lifecycle.State. LifecycleEffects, che ti consente di eseguire un blocco in base a unLifecycle.Eventspecifico.
Queste integrazioni forniscono hook pratici per gestire i cicli di vita all'interno della gerarchia di Compose. Questo documento descrive come utilizzarli nella tua app.
Raccogliere lo stato del ciclo di vita con i flussi
Lifecycle espone una proprietà currentStateFlow che fornisce l'Lifecycle.State corrente
come StateFlow Kotlin. Puoi raccogliere questo Flow come
State. In questo modo, la tua app può leggere le modifiche nel ciclo di vita durante la composizione.
val lifecycleOwner = LocalLifecycleOwner.current
val stateFlow = lifecycleOwner.lifecycle.currentStateFlow
…
val currentLifecycleState by stateFlow.collectAsState()
L'esempio precedente è accessibile utilizzando il modulo lifecycle-common. Il metodo
currentStateAsState() è disponibile nel modulo lifecycle-runtime-compose, che ti consente di leggere comodamente lo stato attuale del ciclo di vita con una
sola riga. L'esempio seguente lo dimostra:
val lifecycleOwner = LocalLifecycleOwner.current
val currentLifecycleState = lifecycleOwner.lifecycle.currentStateAsState()
Eseguire il codice sugli eventi del ciclo di vita
Anziché creare una classe separata che implementa
DefaultLifecycleObserver
e aggiungerla manualmente al ciclo di vita, puoi dichiarare la logica del ciclo di vita inline
utilizzando effetti specifici. LifecycleEffects ti consente di eseguire un blocco quando si verifica un determinato Lifecycle.Event direttamente all'interno della composizione.
LifecycleEventEffect
Utilizza LifecycleEventEffect per eseguire un blocco di codice
quando si verifica un evento specifico. Questa opzione è ideale per eventi una tantum come la registrazione o
l'analisi, in cui non è necessario un risultato immediato o di successo.
@Composable
fun AnalyticsTracker(screenName: String) {
// Log an event when the app receives ON_RESUME (e.g. comes to foreground)
LifecycleEventEffect(Lifecycle.Event.ON_RESUME) {
Analytics.logView(screenName)
}
}
LifecycleStartEffect
Per le operazioni di avvio/arresto accoppiate che devono essere eseguite durante l'avvio dell'app
(visibile) e liberate spazio all'arresto dell'app (in background), utilizza
LifecycleStartEffect.
Come altri effetti di Composizione (ad esempio LaunchedEffect), LifecycleStartEffect
accetta chiavi. Quando la chiave cambia, il blocco viene eseguito di nuovo.
Quando si verifica un evento Lifecycle.Event.ON_STOP o l'effetto esce dalla
composizione, viene eseguito il blocco onStopOrDispose per liberare spazio da qualsiasi lavoro che
faceva parte del blocco iniziale.
@Composable
fun LocationMonitor(locationManager: LocationManager) {
// Starts monitoring when ON_START is dispatched
// Stops monitoring when ON_STOP is dispatched
// (or the composable leaves the screen)
LifecycleStartEffect(locationManager) {
val listener = LocationListener { location ->
/* update UI */
}
locationManager.requestLocationUpdates(listener)
// The cleanup block automatically runs on ON_STOP or on disposal
onStopOrDispose {
locationManager.removeUpdates(listener)
}
}
}
Per informazioni su altri tipi di effetti collaterali, vedi Effetti collaterali in Compose.
LifecycleResumeEffect
LifecycleResumeEffect funziona allo stesso modo di LifecycleStartEffect,
ma è associato all'evento Lifecycle.Event.ON_RESUME. Fornisce inoltre un blocco onPauseOrDispose che esegue la pulizia quando viene inviato ON_PAUSE o quando il composable esce dallo schermo.
Questa API è utile per le risorse che devono essere attive solo quando l'utente interagisce con l'app, ad esempio videocamere o animazioni.
@Composable
fun CameraPreview(cameraController: CameraController) {
LifecycleResumeEffect(cameraController) {
cameraController.startPreview()
onPauseOrDispose {
cameraController.stopPreview()
}
}
}
Accedere a LifecycleOwner
In Compose, l'LifecycleOwner è disponibile implicitamente tramite CompositionLocal denominato LocalLifecycleOwner. Per
impostazione predefinita, l'host principale della gerarchia di composizione fornisce questo proprietario.
val lifecycleOwner = LocalLifecycleOwner.current
Per molte app, l'ispezione di questo proprietario predefinito o il suo passaggio a effetti
sensibili al ciclo di vita è sufficiente. Tuttavia, per la navigazione personalizzata o i layout complessi, potresti
voler creare il tuo LifecycleOwner per definire gli stati del ciclo di vita in
sezioni specifiche della UI. Ad esempio, le librerie di navigazione (come Navigation
3) lo fanno automaticamente per dare a ogni
singola schermata il proprio ciclo di vita.
Crea un LifecycleOwner personalizzato
L'API rememberLifecycleOwner() ti consente di creare e memorizzare un
LifecycleOwner personalizzato. Ciò è particolarmente utile per componenti come un
HorizontalPager, in cui vuoi che solo la pagina visibile e stabile sia
RESUMED, mentre imposti un maxState di STARTED per le pagine adiacenti e fuori schermo.
val pagerState = rememberPagerState(pageCount = { 10 })
HorizontalPager(state = pagerState) { pageNum ->
val pageLifecycleOwner = rememberLifecycleOwner(
maxState = if (pagerState.settledPage == pageNum) {
Lifecycle.State.RESUMED
} else {
Lifecycle.State.STARTED
}
)
CompositionLocalProvider(LocalLifecycleOwner provides pageLifecycleOwner) {
// Your pages here. Their lifecycle-aware components respect the
// custom maxState defined above.
}
}
Per ulteriori informazioni su CompositionLocal, consulta Dati con ambito locale con
CompositionLocal.
Best practice per i componenti sensibili al ciclo di vita
- Mantieni i controller dell'interfaccia utente il più semplici possibile. Non
deve tentare di acquisire i propri dati; utilizza invece un
ViewModelper farlo e osserva un oggettoStateFlowper riflettere le modifiche nell'interfaccia utente. - Prova a scrivere UI basate sui dati in cui la responsabilità del controller UI è quella di
aggiornare la UI man mano che i dati cambiano o notificare le azioni dell'utente al
ViewModel. - Inserisci la logica dei dati nella classe
ViewModel.ViewModeldeve fungere da connettore tra il controller UI e il resto dell'app. Fai attenzione, però, non è responsabilità diViewModelrecuperare i dati (ad esempio da una rete). Invece,ViewModeldeve chiamare il componente appropriato per recuperare i dati, quindi fornire il risultato al controller UI. - Utilizza le coroutine Kotlin per gestire le attività a lunga esecuzione e altre operazioni che possono essere eseguite in modo asincrono.
- Mantieni la logica di avvio/arresto all'interno del composable che ne ha effettivamente bisogno. In questo modo, la logica viene rimossa automaticamente se questo specifico elemento dell'interfaccia utente viene rimosso dalla schermata (ad esempio, all'interno di un grafico di navigazione o quando la visibilità è condizionale).
- Utilizza
collectAsStateWithLifecycleper i dati. Non avviare o interrompere manualmente la raccoltaFlowin base agli eventi del ciclo di vita. Utilizza invececollectAsStateWithLifecycleper convertire i flussi in stato della UI in modo efficiente. In questo modo si risparmiano batteria e risorse perché leFlowvengono messe in pausa quando l'app è in background.
Per ulteriori informazioni sugli Flow, vedi Altri tipi di stato supportati.
Casi d'uso per i componenti sensibili al ciclo di vita
I componenti sensibili al ciclo di vita possono semplificare notevolmente la gestione dei cicli di vita in una serie di casi. Ecco alcuni esempi:
- Alternare gli aggiornamenti della posizione approssimativa e precisa. Utilizza
LifecycleStartEffectper attivare aggiornamenti della posizione granulari mentre la tua app è visibile (ON_START) e libera spazio automaticamente per il listener o passa ad aggiornamenti meno granulari quando l'app è in background (ON_STOP). - Interruzione e avvio del buffering video. Utilizza
LifecycleResumeEffectper posticipare la riproduzione effettiva del video finché l'app non è completamente in primo piano e interattiva (ON_RESUME) e per assicurarti che la riproduzione si interrompa e rilasci le risorse quando l'app viene eseguita in background (ON_PAUSE). - Avvio e interruzione dello streaming di rete. Utilizza
collectAsStateWithLifecycleper osservare flussi continui di dati (come un flusso Kotlin da un socket di rete). In questo modo, l'aggiornamento avviene in tempo reale mentre un'app è in primo piano e la raccolta viene annullata automaticamente quando l'app passa in background. - Mettere in pausa e riprendere le attività pesanti. Utilizza
LifecycleResumeEffectper gestire la sospensione degli aggiornamenti visivi pesanti quando l'app è in background e riprendili dopo che l'app è in primo piano.
Gestione sicura degli eventi ON_STOP
Compose è progettato per gestire in sicurezza gli eventi ON_STOP.
- Stato sicuro:puoi aggiornare
MutableState(ad esempio conuiState.value = ...) in qualsiasi momento, anche quando l'app è in background. Compose attende che l'app sia visibile per eseguire il rendering delle modifiche. - Pulizia automatica:con effetti come
LifecycleStartEffect, il blocco di pulizia (onStopOrDispose) viene eseguito esattamente quando il ciclo di vita passa aSTOPPED. In questo modo, non puoi utilizzare risorse pesanti (come la fotocamera o la posizione) mentre l'app è in background.
Per saperne di più su MutableState, consulta Stato in Jetpack Compose.
Risorse aggiuntive
Per scoprire di più sulla gestione dei cicli di vita con componenti sensibili al ciclo di vita, consulta le seguenti risorse aggiuntive.
Visualizza contenuti
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Panoramica di LiveData
- Utilizzare le coroutine Kotlin con componenti sensibili al ciclo di vita
- Modulo Saved State per ViewModel