Fragment Lifecycle ist eine streng definierte Sequenz von Callback-Methoden, die Android während der Lebensdauer eines Fragment aufruft: von der Erstellung (onAttach) bis zur vollständigen Entfernung (onDetach). Fragment hat einen komplexeren Lebenszyklus als Activity — er umfasst 11 Zustände und 7 Haupt-Callbacks. Der Fragment Lifecycle wird über FragmentManager verwaltet und ist eng mit dem Lebenszyklus der enthaltenen Activity verbunden. Laut Google wird Fragment in 74% der Android-Anwendungen verwendet, die auf API Level 21+ laufen, was das Verständnis des Fragment Lifecycle für die professionelle Android-Entwicklung unerlässlich macht. Die Android-Dokumentation zum Fragment Lifecycle beschreibt alle Zustände und Aufrufgarantien.
Wichtige Punkte
Fragment Lifecycle ist eine Reihe miteinander verbundener Zustände und Methoden, die jede Fragment-Instanz von der Erstellung bis zur Zerstörung durchläuft. Im Gegensatz zur Activity ist der Lebenszyklus von Fragment an zwei Kontexte gebunden: das Fragment selbst (lebt von onAttach bis onDetach) und seine View (lebt von onCreateView bis onDestroyView). Diese Trennung ist ein Hauptmerkmal von Fragment, das es ihm ermöglicht, die Zerstörung der View bei Bildschirmdrehung zu überleben, ohne das Fragment selbst zu zerstören.
Vollständige Sequenz der Fragment-Callbacks:
Laut Google durchläuft der durchschnittliche Fragment in einer modernen Anwendung 3–5 Mal pro Benutzersitzung den vollständigen Zyklus (aufgrund von Bildschirmdrehungen und Navigation). Die korrekte Handhabung aller Phasen ist die Grundlage der UI-Stabilität.
FragmentManager verwaltet Fragment über fünf Hauptzustände, die in der Klasse Fragment.State definiert sind. Jeder Zustand entspricht einer bestimmten Menge von Callbacks, die ausgeführt wurden.
| Zustand | Bedeutung | Ausgeführte Callbacks |
|---|---|---|
| INITIALIZED | Fragment wurde erstellt, aber View ist noch nicht verfügbar | onAttach, onCreate |
| CREATED | View wurde erstellt, aber Fragment ist nicht sichtbar | + onCreateView, onViewCreated |
| STARTED | Fragment ist sichtbar, aber nicht aktiv | + onStart |
| RESUMED | Fragment ist aktiv und interagiert mit dem Benutzer | + onResume |
| DESTROYED | Fragment wurde zerstört | + onDestroyView, onDestroy, onDetach |
FragmentManager bewegt Fragment zwischen Zuständen basierend auf Benutzeraktionen und Systemereignissen. Beim Hinzufügen eines Fragment zu einem Container durchläuft es nacheinander INITIALIZED → CREATED → STARTED → RESUMED. Beim Entfernen — RESUMED → STARTED → CREATED → DESTROYED.
Der CREATED-Zustand ist besonders: Die View kann zerstört werden (nach onDestroyView), aber das Fragment selbst bleibt im Zustand CREATED (nach onDestroyView, vor onDestroy). Dies ermöglicht FragmentManager, das Fragment ohne View im Speicher zu behalten, was zum Überleben von Bildschirmdrehungen notwendig ist.
Fragment Lifecycle und Activity Lifecycle sind eng verwandt, haben aber grundlegende Unterschiede. Fragment lebt immer innerhalb einer Activity, und sein Lebenszyklus hängt von der Host-Activity ab, ist aber nicht identisch mit ihr.
| Aspekt | Activity | Fragment |
|---|---|---|
| Anzahl der Callbacks | 7 (onCreate … onDestroy) | 11 (onAttach … onDetach) |
| Separater Lifecycle für View | Nein | Ja (viewLifecycleOwner) |
| Überlebt Drehung | Nein (wird zerstört) | Ja (ViewModel + Fragment überleben) |
| Abhängigkeit vom Host | Nein | Abhängig vom Activity Lifecycle |
| Zustandsspeicherung | onSaveInstanceState | onSaveInstanceState (Fragment-Ebene) |
| Verwaltung | System | FragmentManager |
Der wichtigste praktische Unterschied: Bei Bildschirmdrehung wird die Activity vollständig zerstört (onDestroy) und neu erstellt (onCreate). Fragment durchläuft bei der Drehung onDestroyView (View wird zerstört) → onCreateView (View wird neu erstellt), aber das Fragment selbst und sein ViewModel bleiben lebendig. Dies macht Fragment zu einem idealen Container für UI-Logik, die Konfigurationsänderungen überleben muss.
Aufrufreihenfolge bei Bildschirmdrehung: Activity.onPause → Fragment.onPause → Activity.onStop → Fragment.onStop → Activity.onDestroy → Fragment.onDestroyView → (Activity zerstört) → Activity.onCreate → Fragment.onAttach → Fragment.onCreate → Fragment.onCreateView → Fragment.onViewCreated → Activity.onStart → Fragment.onStart → Activity.onResume → Fragment.onResume.
FragmentManager ist die zentrale Klasse, die für das Hinzufügen, Entfernen und Ersetzen von Fragmenten sowie die Verwaltung ihrer Zustände verantwortlich ist. FragmentManager verwaltet den BackStack und gewährleistet die korrekte Callback-Reihenfolge bei Transaktionen. Jede Activity und jedes verschachtelte Fragment hat seinen eigenen FragmentManager.
Hauptoperationen von FragmentManager:
BackStack ist der Transaktionsstapel von FragmentManager. Beim Drücken der System-Zurück-Taste wird die letzte Transaktion im BackStack rückgängig gemacht (popBackStack()). Ein über popBackStack entferntes Fragment wird wiederhergestellt. Wenn der BackStack leer ist, beendet das Drücken von Zurück die Activity.
Laut Google stehen 78% der Fragment-Probleme (Duplizierung, leere Bildschirme, IllegalStateException) im Zusammenhang mit falscher Verwendung von FragmentManager. Die Hauptregel: Führen Sie Transaktionen je nach Kontext über commit() (asynchron) oder commitNow() (synchron) aus. commit() gewährleistet die korrekte Reihenfolge bei mehreren Transaktionen.
Fragment unterstützt einen eigenen Mechanismus zur Zustandsspeicherung über onSaveInstanceState, der unabhängig von der Activity funktioniert. Fragment speichert den Zustand in einem Bundle, das bei der Wiederherstellung an onCreate und onCreateView übergeben wird.
Wann Fragment den Zustand speichert:
Moderner Ansatz: Verwenden Sie SavedStateHandle im ViewModel zum Speichern des Fragment-Zustands. SavedStateHandle speichert und stellt Daten automatisch bei Bildschirmdrehung und Prozessende wieder her, ohne manuelles onSaveInstanceState. Google empfiehlt SavedStateHandle als bevorzugte Methode zum Speichern des UI-Zustands in Fragment.
setRetainInstance (veraltet seit Fragment 1.3): Früher konnte Fragment über setRetainInstance(true) bei Bildschirmdrehung beibehalten werden. Dieser Ansatz wurde durch ViewModel + SavedStateHandle ersetzt, die zuverlässiger funktionieren und keine spezielle Konfiguration erfordern.
viewLifecycleOwner ist ein Lifecycle, der an die Fragment-View gebunden ist (von onCreateView bis onDestroyView). Dies ist ein grundlegend wichtiges Konzept: Über viewLifecycleOwner getätigte LiveData/Flow-Abonnements werden automatisch gekündigt, wenn die View zerstört wird (onDestroyView), beeinflussen aber nicht das Fragment selbst.
Unterschied zwischen viewLifecycleOwner und Fragment-Lifecycle:
Warum das wichtig ist: Wenn Sie LiveData über den Fragment-Lifecycle (this) abonnieren, bleibt das Abonnement nach onDestroyView aktiv und LiveData versucht, eine null-View zu aktualisieren, was eine NPE verursacht. Das Abonnieren über viewLifecycleOwner garantiert, dass nach onDestroyView keine UI-Aktualisierungen erfolgen.
Regel: Verwenden Sie im Fragment immer viewLifecycleOwner für Abonnements von LiveData, Flow und UI-bezogenen Koroutinen. Für ViewModel-Koroutinen verwenden Sie viewModelScope — es ist an ViewModel gebunden, nicht an Fragment.
Zeigt korrekte UI-Initialisierung und LiveData-Abonnement über viewLifecycleOwner.
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", "Liste wird aktualisiert: ${users.size} Benutzer")
}
}
override fun onDestroyView() {
super.onDestroyView()
Log.d("UserListFragment", "onDestroyView: View zerstört")
}
}
Fragment inflatet das Layout in onCreateView, konfiguriert die UI und abonniert LiveData in onViewCreated. Das Abonnement über viewLifecycleOwner ist eine zwingende Anforderung zur Vermeidung von Speicherlecks. onDestroyView protokolliert die Zerstörung der View — Bestätigung, dass Fragment die Bildschirmdrehung überlebt.
Zeigt das Hinzufügen von Fragment über FragmentManager in Activity, Ersetzung mit BackStack und Wiederherstellung.
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", "Lade Benutzerdetails: $userId")
}
}
Activity verwendet supportFragmentManager zur Verwaltung von Fragmenten. Die add()-Transaktion mit BackStack stellt sicher, dass HomeFragment beim Drücken von Zurück wiederhergestellt wird. openDetail() ersetzt das aktuelle Fragment durch DetailFragment mit Argumenten. Die Prüfung auf savedInstanceState == null verhindert Fragment-Duplizierung bei Bildschirmdrehung.
Verwendung von Flow und StateFlow in Fragment mit viewLifecycleOwner für reaktive UI-Updates.
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", "Suchergebnisse: ${results.size}")
}
}
}
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
}
Fragment verwendet View Binding für den View-Zugriff. Die Koroutine viewLifecycleOwner.lifecycleScope.launch wird automatisch abgebrochen, wenn die View zerstört wird. Binding wird in onDestroyView auf null gesetzt, um Speicherlecks zu vermeiden. StateFlow stellt die Aktualität der Daten bei Neuerstellung der View sicher.
Häufig gestellte Fragen
onCreateView erstellt und gibt die root-View des Fragment zurück. onViewCreated wird unmittelbar nach der Erstellung der View aufgerufen und garantiert, dass die View vollständig initialisiert und für die Konfiguration (findViewById, Abonnements) bereit ist. Google empfiehlt, in onCreateView nur das Layout zu inflaten und die gesamte UI-Konfiguration in onViewCreated durchzuführen.
onDestroy — Fragment wird als Objekt zerstört (ViewModel wird bereinigt, Koroutinen werden abgebrochen). onDetach ist der letzte Callback, nach dem Fragment von der Activity getrennt wird. Praktisch alle Ressourcen sollten in onDestroyView (View) und onDestroy (Fragment) freigegeben werden. onDetach dient zum Bereinigen von Referenzen auf die Activity.
Fragment verschwindet, wenn es nicht über eine Transaktion mit BackStack-Erhaltung zu FragmentManager hinzugefügt wurde oder wenn Activity FragmentManager in onCreate nicht wiederherstellt. Lösung: Fügen Sie Fragment programmatisch über supportFragmentManager.beginTransaction().add() in onCreate mit einer savedInstanceState == null-Prüfung hinzu.
Nein. Fragment ist immer über FragmentManager an eine Activity gebunden. Selbst bei Bildschirmdrehung wird Activity neu erstellt und Fragment wird an die neue Activity wieder angebunden. Ein Fragment außerhalb einer Activity zu erstellen ist unmöglich — der Fragment-Konstruktor erfordert einen leeren Konstruktor für die Systemwiederherstellung.
Verschachtelte Fragmente (nested fragments) sind Fragmente innerhalb eines anderen Fragments. Sie werden zum Erstellen komplexer Bildschirme verwendet: Tab-Panels, Panel mit Registerkarten, Master-Detail. Verschachtelte Fragmente werden vom untergeordneten FragmentManager (childFragmentManager) verwaltet. Google empfiehlt, nicht mehr als 2 Verschachtelungsebenen zu überschreiten, um Leistungsprobleme zu vermeiden.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch