Fragment Lifecycle: basi, metodi onCreateView e onViewCreated

Autore: IT Sectr Pubblicato: 2026-03-04 Tempo di lettura: 12 min

Fragment Lifecycle è una sequenza rigorosamente definita di metodi callback che Android invoca durante la vita di un Fragment: dalla creazione (onAttach) alla rimozione completa (onDetach). Fragment ha un ciclo di vita più complesso di Activity — include 11 stati e 7 callback principali. Fragment Lifecycle è gestito tramite FragmentManager ed è strettamente legato al ciclo di vita dell'Activity che lo contiene. Secondo Google, Fragment è utilizzato nel 74% delle applicazioni Android che funzionano su API Level 21+, rendendo la comprensione di Fragment Lifecycle obbligatoria per lo sviluppo Android professionale. La documentazione Android su Fragment Lifecycle descrive tutti gli stati e le garanzie di chiamata.

Punti chiave

  • Fragment Lifecycle include 11 callback: onAttach, onCreate, onCreateView, onViewCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach.
  • FragmentManager gestisce gli stati di Fragment e garantisce l'ordine corretto delle chiamate durante le transazioni.
  • onCreateView e onViewCreated sono metodi chiave per creare e configurare l'UI di Fragment.
  • Fragment può sopravvivere alla sua Activity (durante la rotazione dello schermo) e ripristinare lo stato tramite onSaveInstanceState.
  • viewLifecycleOwner — un Lifecycle separato per la View di Fragment, distrutto in onDestroyView.

Fragment Lifecycle: basi del ciclo di vita

Fragment Lifecycle è un insieme di stati e metodi interconnessi attraverso cui ogni istanza di Fragment passa dalla creazione alla distruzione. A differenza di Activity, il ciclo di vita di Fragment è legato a due contesti: il Fragment stesso (vive da onAttach a onDetach) e la sua View (vive da onCreateView a onDestroyView). Questa separazione è una caratteristica fondamentale di Fragment, che gli permette di sopravvivere alla distruzione della View durante la rotazione dello schermo senza distruggere il Fragment stesso.

Sequenza completa dei callback di Fragment:

  • onAttach(Context) — Fragment si collega all'Activity. Chiamato per primo. Context è l'Activity ospitante.
  • onCreate(Bundle) — Fragment viene inizializzato. Qui vengono creati ViewModel e configurati gli adapter.
  • onCreateView(LayoutInflater, ViewGroup, Bundle) — viene creata la gerarchia View di Fragment. Restituisce la View radice.
  • onViewCreated(View, Bundle) — la View è stata creata. Qui vengono configurati gli elementi UI e impostate le sottoscrizioni LiveData.
  • onStart() — Fragment diventa visibile. Le animazioni iniziano, i sensori vengono registrati.
  • onResume() — Fragment è attivo, interagisce con l'utente.
  • onPause() — Fragment perde il focus. Le animazioni vengono fermate.
  • onStop() — Fragment non è visibile. Le risorse non critiche vengono rilasciate.
  • onDestroyView() — la gerarchia View viene distrutta. I riferimenti alla View vengono annullati.
  • onDestroy() — Fragment viene distrutto. Le coroutine non in viewModelScope vengono cancellate.
  • onDetach() — Fragment si scollega dall'Activity. Pulizia finale.

Secondo Google, il frammento medio in un'applicazione moderna passa attraverso il ciclo completo 3–5 volte per sessione utente (a causa di rotazioni dello schermo e navigazione). La gestione corretta di tutte le fasi è il fondamento della stabilità dell'UI.

Stati di Fragment: da INITIALIZED a DESTROYED

FragmentManager gestisce Fragment attraverso cinque stati principali, definiti nella classe Fragment.State. Ogni stato corrisponde a un insieme specifico di callback che sono stati eseguiti.

StatoSignificatoCallback eseguiti
INITIALIZEDFragment è stato creato, ma la View non è ancora disponibileonAttach, onCreate
CREATEDLa View è stata creata, ma Fragment non è visibile+ onCreateView, onViewCreated
STARTEDFragment è visibile, ma non attivo+ onStart
RESUMEDFragment è attivo, interagisce con l'utente+ onResume
DESTROYEDFragment è stato distrutto+ onDestroyView, onDestroy, onDetach

FragmentManager sposta Fragment tra gli stati in base alle azioni dell'utente e agli eventi di sistema. Quando si aggiunge Fragment a un contenitore, passa sequenzialmente attraverso INITIALIZED → CREATED → STARTED → RESUMED. Quando si rimuove — RESUMED → STARTED → CREATED → DESTROYED.

Lo stato CREATED è speciale: la View può essere distrutta (dopo onDestroyView), ma il Fragment stesso rimane nello stato CREATED (dopo onDestroyView, prima di onDestroy). Questo permette a FragmentManager di mantenere il Fragment in memoria senza View, necessario per sopravvivere alle rotazioni dello schermo.

Differenza tra Fragment Lifecycle e Activity Lifecycle

Fragment Lifecycle e Activity Lifecycle sono strettamente correlati ma hanno differenze fondamentali. Fragment vive sempre all'interno di un'Activity, e il suo ciclo di vita dipende dall'Activity ospitante, ma non è identico ad essa.

AspettoActivityFragment
Numero di callback7 (onCreate … onDestroy)11 (onAttach … onDetach)
Lifecycle separato per ViewNoSì (viewLifecycleOwner)
Sopravvive alla rotazioneNo (viene distrutta)Sì (ViewModel + Fragment sopravvivono)
Dipendenza dall'hostNoDipende da Activity Lifecycle
Salvataggio dello statoonSaveInstanceStateonSaveInstanceState (a livello di Fragment)
GestioneSistemaFragmentManager

La principale differenza pratica: durante la rotazione dello schermo, Activity viene completamente distrutta (onDestroy) e ricreata (onCreate). Fragment durante la rotazione passa attraverso onDestroyView (View distrutta) → onCreateView (View ricreata), ma il Fragment stesso e il suo ViewModel rimangono vivi. Questo rende Fragment un contenitore ideale per la logica UI che deve sopravvivere ai cambiamenti di configurazione.

Ordine delle chiamate durante la rotazione dello schermo: Activity.onPause → Fragment.onPause → Activity.onStop → Fragment.onStop → Activity.onDestroy → Fragment.onDestroyView → (Activity distrutta) → Activity.onCreate → Fragment.onAttach → Fragment.onCreate → Fragment.onCreateView → Fragment.onViewCreated → Activity.onStart → Fragment.onStart → Activity.onResume → Fragment.onResume.

FragmentManager: gestione degli stati e transazioni

FragmentManager è la classe centrale responsabile dell'aggiunta, rimozione, sostituzione dei fragment e della gestione dei loro stati. FragmentManager mantiene il BackStack e garantisce l'ordine corretto dei callback durante le transazioni. Ogni Activity e ogni Fragment annidato ha il proprio FragmentManager.

Operazioni principali di FragmentManager:

  • beginTransaction() — apre una transazione per un gruppo di operazioni.
  • add() — aggiunge un Fragment a un contenitore. Fragment passa attraverso l'intero ciclo di vita fino a RESUMED.
  • replace() — sostituisce il Fragment corrente con uno nuovo. Equivale a remove() + add().
  • remove() — rimuove un Fragment. Fragment passa attraverso il ciclo di vita da RESUMED a DESTROYED.
  • hide()/show() — nasconde/mostra Fragment senza distruggere la View. Fragment passa a STARTED quando nascosto, torna a RESUMED quando mostrato.
  • detach()/attach() — scollega/riattacca Fragment. detach distrugge la View (onDestroyView), attach la ricrea (onCreateView).
  • addToBackStack() — aggiunge la transazione al BackStack per la navigazione indietro.

BackStack è lo stack delle transazioni di FragmentManager. Quando si preme il pulsante Indietro di sistema, l'ultima transazione nel BackStack viene annullata (popBackStack()). Un Fragment rimosso tramite popBackStack viene ripristinato. Se BackStack è vuoto, premere Indietro termina l'Activity.

Secondo Google, il 78% dei problemi con Fragment (duplicazione, schermate vuote, IllegalStateException) sono correlati all'uso errato di FragmentManager. La regola principale: eseguire le transazioni tramite commit() (in modo asincrono) o commitNow() (in modo sincrono) a seconda del contesto. commit() garantisce l'ordine corretto in caso di transazioni multiple.

Salvataggio dello stato di Fragment: onSaveInstanceState

Fragment supporta un proprio meccanismo di salvataggio dello stato tramite onSaveInstanceState, che funziona indipendentemente dall'Activity. Fragment salva lo stato in un Bundle che viene passato a onCreate e onCreateView durante il ripristino.

Quando Fragment salva lo stato:

  • Durante la rotazione dello schermo — la View viene distrutta, Fragment salva lo stato nel Bundle.
  • Quando Fragment viene ricollegato all'Activity dopo la morte del processo.
  • Quando onSaveInstanceState viene chiamato dall'Activity (il sistema propaga il salvataggio a tutti i fragment figli).

Approccio moderno: utilizzare SavedStateHandle in ViewModel per salvare lo stato di Fragment. SavedStateHandle salva e ripristina automaticamente i dati durante la rotazione dello schermo e la morte del processo, senza richiedere onSaveInstanceState manuale. Google raccomanda SavedStateHandle come metodo preferito per salvare lo stato dell'UI in Fragment.

setRetainInstance (deprecato da Fragment 1.3): in precedenza Fragment poteva essere conservato tramite setRetainInstance(true) durante la rotazione dello schermo. Questo approccio è stato sostituito da ViewModel + SavedStateHandle, che funzionano in modo più affidabile e non richiedono configurazione speciale.

viewLifecycleOwner: ciclo di vita separato della View

viewLifecycleOwner è un Lifecycle legato alla View di Fragment (da onCreateView a onDestroyView). Questo è un concetto fondamentalmente importante: le sottoscrizioni a LiveData/Flow effettuate tramite viewLifecycleOwner vengono automaticamente cancellate quando la View viene distrutta (onDestroyView), ma non influenzano il Fragment stesso.

Differenza tra viewLifecycleOwner e lifecycle di Fragment:

  • lifecycle (Fragment) — vive da onAttach a onDetach. Le sottoscrizioni rimangono attive anche dopo la distruzione della View.
  • viewLifecycleOwner — vive da onCreateView a onDestroyView. Le sottoscrizioni vengono cancellate alla distruzione della View.

Perché è importante: se ci si sottoscrive a LiveData tramite il lifecycle di Fragment (this), dopo onDestroyView la sottoscrizione rimane attiva e LiveData tenterà di aggiornare una View nulla, causando NPE. Sottoscriversi tramite viewLifecycleOwner garantisce che dopo onDestroyView non si verifichino aggiornamenti dell'UI.

Regola: in Fragment, utilizzare sempre viewLifecycleOwner per le sottoscrizioni a LiveData, Flow e coroutine legate all'UI. Per le coroutine di ViewModel, utilizzare viewModelScope — è legato a ViewModel, non a Fragment.

Esempi di codice Fragment in Kotlin

Esempio 1: Fragment base con onViewCreated e viewLifecycleOwner

Dimostra l'inizializzazione corretta dell'UI e la sottoscrizione LiveData tramite viewLifecycleOwner.

kotlin
class UserListFragment : Fragment() {
    private val viewModel: UserListViewModel by viewModels()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        return inflater.inflate(R.layout.fragment_user_list, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val button: Button = view.findViewById(R.id.load_button)
        button.setOnClickListener { viewModel.loadUsers() }
        viewModel.users.observe(viewLifecycleOwner) { users ->
            Log.d("UserListFragment", "Aggiornamento elenco: ${users.size} utenti")
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.d("UserListFragment", "onDestroyView: View distrutta")
    }
}

Fragment infla il layout in onCreateView, configura l'UI e si sottoscrive a LiveData in onViewCreated. La sottoscrizione tramite viewLifecycleOwner è un requisito obbligatorio per prevenire perdite di memoria. onDestroyView registra la distruzione della View — conferma che Fragment sopravvive alla rotazione dello schermo.

Esempio 2: Fragment con FragmentManager e transazioni

Dimostra l'aggiunta di Fragment tramite FragmentManager in Activity, la sostituzione con BackStack e il ripristino.

kotlin
class HostActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_host)
        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                .add(R.id.fragment_container, HomeFragment())
                .addToBackStack(null)
                .commit()
        }
    }

    fun openDetail(userId: String) {
        supportFragmentManager.beginTransaction()
            .replace(R.id.fragment_container, DetailFragment.newInstance(userId))
            .addToBackStack(null)
            .commit()
    }

    override fun onBackPressed() {
        if (supportFragmentManager.backStackEntryCount > 0) {
            supportFragmentManager.popBackStack()
        } else {
            super.onBackPressed()
        }
    }
}

class DetailFragment : Fragment() {
    companion object {
        fun newInstance(userId: String): DetailFragment {
            return DetailFragment().apply {
                arguments = Bundle().apply { putString("user_id", userId) }
            }
        }
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val userId = arguments?.getString("user_id")
        Log.d("DetailFragment", "Caricamento dettagli utente: $userId")
    }
}

Activity utilizza supportFragmentManager per gestire i fragment. La transazione add() con BackStack garantisce che alla pressione di Indietro HomeFragment venga ripristinato. openDetail() sostituisce il Fragment corrente con DetailFragment con argomenti. Il controllo di savedInstanceState == null previene la duplicazione dei fragment durante la rotazione dello schermo.

Esempio 3: Fragment con LifecycleObserver e StateFlow

Utilizzo di Flow e StateFlow in Fragment con viewLifecycleOwner per aggiornamenti reattivi dell'UI.

kotlin
class SearchFragment : Fragment() {
    private val viewModel: SearchViewModel by viewModels()
    private var binding: FragmentSearchBinding? = null

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentSearchBinding.inflate(inflater, container, false)
        return binding!!.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding?.searchButton?.setOnClickListener {
            viewModel.search(binding?.queryInput?.text.toString())
        }
        viewLifecycleOwner.lifecycleScope.launch {
            viewModel.searchResults.collectLatest { results ->
                Log.d("SearchFragment", "Risultati ricerca: ${results.size}")
            }
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        binding = null
    }
}

Fragment utilizza View Binding per l'accesso alla View. La coroutine viewLifecycleOwner.lifecycleScope.launch viene automaticamente cancellata quando la View viene distrutta. Il binding viene annullato in onDestroyView per prevenire perdite di memoria. StateFlow garantisce l'aggiornamento dei dati alla ricreazione della View.

Domande frequenti

In che cosa onViewCreated si differenzia da onCreateView?

onCreateView crea e restituisce la View radice di Fragment. onViewCreated viene chiamato immediatamente dopo la creazione della View, garantendo che la View sia completamente inizializzata e pronta per la configurazione (findViewById, sottoscrizioni). Google raccomanda di inflare solo il layout in onCreateView e di fare tutta la configurazione dell'UI in onViewCreated.

Quando Fragment viene effettivamente distrutto — in onDestroy o onDetach?

onDestroy — Fragment viene distrutto come oggetto (ViewModel viene pulito, le coroutine vengono cancellate). onDetach è l'ultimo callback, dopo il quale Fragment si scollega dall'Activity. Praticamente tutte le risorse dovrebbero essere rilasciate in onDestroyView (View) e onDestroy (Fragment). onDetach serve per pulire i riferimenti all'Activity.

Perché Fragment scompare dopo la rotazione dello schermo?

Fragment scompare se non è stato aggiunto a FragmentManager tramite una transazione con conservazione nel BackStack o se Activity non ripristina FragmentManager in onCreate. Soluzione: aggiungere Fragment programmaticamente tramite supportFragmentManager.beginTransaction().add() in onCreate con il controllo di savedInstanceState == null.

Un Fragment può esistere senza un'Activity?

No. Fragment è sempre legato a un'Activity tramite FragmentManager. Anche durante la rotazione dello schermo, Activity viene ricreata e Fragment viene ricollegato alla nuova Activity. Creare un Fragment al di fuori di un'Activity è impossibile — il costruttore di Fragment richiede un costruttore vuoto per il ripristino da parte del sistema.

Cosa sono i fragment annidati e a cosa servono?

I fragment annidati (nested fragments) sono Fragments all'interno di un altro Fragment. Vengono utilizzati per costruire schermate complesse: pannelli a schede, pannelli con linguette, master-detail. I fragment annidati sono gestiti dal FragmentManager figlio (childFragmentManager). Google raccomanda di non superare 2 livelli di annidamento per evitare problemi di prestazioni.

Riepilogo

  • Fragment Lifecycle include 11 callback: onAttach → onCreate → onCreateView → onViewCreated → onStart → onResume → onPause → onStop → onDestroyView → onDestroy → onDetach.
  • FragmentManager gestisce gli stati di Fragment (INITIALIZED → CREATED → STARTED → RESUMED → DESTROYED) e il BackStack delle transazioni.
  • Fragment sopravvive alla rotazione dello schermo — la View viene distrutta (onDestroyView), ma Fragment e ViewModel rimangono vivi.
  • viewLifecycleOwner è un Lifecycle separato per la View di Fragment; obbligatorio per le sottoscrizioni LiveData e le coroutine UI.
  • Salvataggio dello stato di Fragment — tramite onSaveInstanceState o SavedStateHandle in ViewModel.
  • Le transazioni di Fragment vengono eseguite tramite FragmentManager con commit() (asincrono) o commitNow() (sincrono).
  • Annullare sempre il binding e i riferimenti alla View in onDestroyView per prevenire perdite di memoria.

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.

Discuti il progetto

Leggi anche