Il ciclo di vita di un'applicazione mobile determina come si comporta all'avvio, alla minimizzazione, al ritorno dallo sfondo e alla chiusura. In questo articolo analizzeremo App Lifecycle (iOS), Activity Lifecycle (Android), Fragment Lifecycle, ViewController Lifecycle e LifecycleOwner. Comprendere questi processi è fondamentale per prevenire perdite di memoria, perdita di dati e un funzionamento errato dell'app. Maggiori dettagli nella documentazione ufficiale di Android Activity Lifecycle.
Punti chiave
Prima di analizzare il ciclo di vita dei singoli schermi, è importante comprendere il ciclo di vita dell'intera applicazione. In iOS, l'app attraversa cinque stati: Not Running (non in esecuzione), Inactive (in background, non riceve eventi), Active (attiva), Background (in background, codice in esecuzione) e Suspended (in background, codice sospeso). Questi stati sono gestiti in AppDelegate tramite i metodi applicationDidFinishLaunching, applicationDidBecomeActive, applicationWillResignActive, applicationDidEnterBackground e applicationWillTerminate.
In Android, l'equivalente è l'Application Lifecycle, tracciato tramite l'interfaccia Application.ActivityLifecycleCallbacks. Tuttavia, Android si concentra maggiormente sul ciclo di vita di un'Activity — un singolo schermo dell'app. Questo perché un'app Android può essere composta da più Activity, ciascuna con il proprio ciclo.
L'approccio moderno in Android è usare ProcessLifecycleOwner dalla libreria lifecycle-process. Permette di tracciare lo stato dell'intero processo senza essere legati a un'Activity specifica. In iOS, si usa UISceneDelegate (da iOS 13) o AppDelegate per tracciare lo stato dell'app. SceneDelegate gestisce più finestre (multiwindow) su iPad. Comprendere l'App Lifecycle è particolarmente importante per IT Sectr nello sviluppo di app con sincronizzazione in background, streaming e chiamate VoIP.
Activity è il componente base di un'app Android, che rappresenta uno schermo. L'Activity ha un ciclo di vita chiaramente definito gestito dal sistema operativo in risposta alle azioni dell'utente e agli eventi di sistema (rotazione dello schermo, chiamata in arrivo, memoria insufficiente).
| Metodo | Descrizione | Cosa fare |
|---|---|---|
| onCreate | Chiamato una volta alla creazione dell'Activity | Inizializzazione UI, findViewById, configurazione ViewModel |
| onStart | L'Activity diventa visibile | Avviare animazioni, registrare BroadCastReceiver |
| onResume | L'Activity ottiene il focus di input | Avviare fotocamera, sensori, animazioni |
| onPause | L'Activity perde il focus (parzialmente visibile) | Salvare bozze, fermare animazioni |
| onStop | L'Activity non è visibile | Liberare risorse, fermare aggiornamenti |
| onDestroy | L'Activity viene distrutta | Pulire tutti i riferimenti, disiscriversi da LiveData |
| onRestart | Chiamato prima di onStart dopo onStop | Reinizializzazione |
Importante: onSaveInstanceState viene chiamato prima di onStop per salvare lo stato temporaneo. Il ripristino avviene in onCreate tramite Bundle savedInstanceState o tramite SavedStateHandle in ViewModel. Senza una corretta gestione del ciclo di vita, l'app perderà tutti i dati non salvati alla rotazione dello schermo.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("draft", draftText)
}
override fun onDestroy() {
super.onDestroy()
// Отписка от всех подписок
}
}
In Jetpack Compose, il ciclo di vita dell'Activity rimane invariato, ma Compose fornisce strumenti aggiuntivi: Composizione consapevole del ciclo di vita tramite LifecycleOwner, effetti LifecycleEventEffect e DisposableEffect per la pulizia automatica delle risorse alla distruzione.
Fragment in Android vive all'interno di un'Activity e ha un proprio ciclo di vita, che si sovrappone parzialmente a quello dell'Activity ma aggiunge nuovi metodi. I Fragment possono essere aggiunti, sostituiti, rimossi senza distruggere l'Activity, rendendoli più flessibili ma anche più complessi.
Metodi chiave del Fragment Lifecycle: onAttach — Fragment allegato all'Activity (prima chiamata); onCreate — inizializzazione dati; onCreateView — creazione della View; onViewCreated — View creata, si può configurare l'UI; onStart — Fragment visibile; onResume — Fragment in focus; onPause — Fragment perde il focus; onStop — Fragment non visibile; onDestroyView — View distrutta; onDestroy — Fragment distrutto; onDetach — Fragment scollegato dall'Activity.
Differenza chiave dall'Activity: onCreateView e onDestroyView possono essere chiamati più volte (ad esempio, durante il cambio di TabLayout), mentre onCreate viene chiamato una volta. Di conseguenza, l'inizializzazione della View deve essere fatta in onViewCreated, non in onCreateView. Le risorse legate alla View (come gli adapter RecyclerView) devono essere pulite in onDestroyView.
UIViewController è la classe base per la gestione degli schermi in iOS. Il suo ciclo di vita consiste in una sequenza di metodi che UIKit chiama automaticamente. Comprendere questo ciclo è fondamentale per una corretta inizializzazione dell'UI, gestione dei dati e della memoria.
| Metodo | Quando viene chiamato | Uso tipico |
|---|---|---|
| loadView | Quando il View Controller carica la sua gerarchia di View | Inizializzazione personalizzata senza storyboard |
| viewDidLoad | Dopo il caricamento della View in memoria (una volta) | Configurazione UI, caricamento dati iniziali |
| viewWillAppear | Prima che la View appaia sullo schermo | Aggiornare dati, iscriversi alle notifiche |
| viewDidAppear | Dopo che la View è apparsa sullo schermo | Avviare animazioni, avviare animazioni di tracciamento |
| viewWillDisappear | Prima che la View scompaia dallo schermo | Salvare stato, annullare iscrizione alle notifiche |
| viewDidDisappear | Dopo che la View è scomparsa dallo schermo | Fermare animazioni, liberare risorse |
| dealloc | Quando il View Controller viene distrutto | Liberare tutte le risorse |
Importante: viewDidLoad viene chiamato solo una volta nella vita del View Controller. Per aggiornare i dati a ogni apparizione, usa viewWillAppear. Se ti iscrivi a NotificationCenter in viewWillAppear, assicurati di annullare l'iscrizione in viewDidDisappear per evitare perdite di memoria.
SwiftUI gestisce il ciclo di vita delle View tramite strutture View. Invece dei metodi callback, SwiftUI usa i modificatori onAppear e onDisappear. Per gli stati globali dell'app, si usa l'App Lifecycle tramite i protocolli App e Scene. SwiftUI gestisce automaticamente la creazione e la distruzione delle View in base allo stato, semplificando lo sviluppo ma richiedendo la comprensione dell'identità e della durata delle View.
struct ContentView: View {
var body: some View {
Text("Hello")
.onAppear {
print("View появилась")
}
.onDisappear {
print("View исчезла")
}
}
}
LifecycleOwner è un'interfaccia di Android Architecture Components che marca un oggetto con un ciclo di vita (Activity, Fragment). LifecycleObserver è un'interfaccia che permette a un oggetto di iscriversi agli eventi di LifecycleOwner. Insieme formano la base della gestione reattiva del ciclo di vita nello sviluppo Android moderno.
Invece di chiamare metodi esplicitamente in onStart/onStop, si consiglia di usare DefaultLifecycleObserver (sostituto del deprecato LifecycleObserver con annotazioni @OnLifecycleEvent). Questo è l'approccio promosso da Google per ViewModel e altri componenti che devono reagire al ciclo di vita senza avere riferimenti diretti ad Activity o Fragment.
class MyObserver : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
// Подписка на обновления
}
override fun onStop(owner: LifecycleOwner) {
// Отписка
}
}
In IT Sectr, usiamo LifecycleOwner in tutti i progetti Android. ViewModel si iscrive al LifecycleOwner dell'Activity tramite viewModelScope e lifecycleScope, garantendo la cancellazione automatica delle coroutine alla distruzione dell'Activity. Questo previene perdite di memoria e rende il codice più pulito e sicuro.
Domande frequenti
L'Activity attraversa sei stati: Created (onCreate), Started (onStart), Resumed (onResume), Paused (onPause), Stopped (onStop), Destroyed (onDestroy).
Ordine: loadView → viewDidLoad → viewWillAppear → viewDidAppear → viewWillDisappear → viewDidDisappear. viewDidLoad viene chiamato una volta.
LifecycleOwner è un componente di Android Architecture Components che possiede il ciclo di vita di un'Activity o di un Fragment. Permette di iscriversi agli eventi tramite LifecycleObserver.
L'app iOS attraversa cinque stati: Not Running, Inactive, Active, Background, Suspended. Le transizioni sono gestite tramite UIApplicationDelegate.
Saved State è il meccanismo di Android per preservare lo stato di Activity/Fragment durante la rotazione dello schermo o la ricreazione del processo. Usa onSaveInstanceState e SavedStateHandle.
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.