Android SharedPreferences Tutorial and Example

Fragment Lifecycle: onAttach to onDetach

A Fragment is a reusable portion of an Android screen, but it is not a miniature Activity. Its lifecycle is controlled by both the FragmentManager and the Activity that hosts it. Understanding each callback helps you place setup, UI work, state restoration, and cleanup in the right location.

The lifecycle begins when the Fragment becomes associated with a context and ends when that association is removed. Between those points, the Fragment itself may remain alive while its view is destroyed and recreated. This distinction is especially important during rotation, split-screen mode, navigation, and process recovery.

For beginners building a ListView, form, or database-driven screen, lifecycle mistakes often appear as null pointer exceptions, duplicated observers, stale views, or lost input. A clear callback sequence makes these errors easier to prevent and debug.

The examples below apply to Android development in Australia as readily as anywhere else. For an app used during a Sydney train commute or on a Melbourne tram, a resilient Fragment should preserve useful state through interrupted sessions and changing connectivity.

Callback Main purpose Suitable work Avoid
onAttach() Connect to the host context Read host interfaces and initialise non-UI dependencies Accessing the Fragment’s view
onCreate() Prepare Fragment state Read arguments and restore non-view data Inflating or binding widgets
onCreateView() Build the view hierarchy Inflate XML and return the root view Starting long-lived observers too early
onViewCreated() Configure the created view Bind widgets, adapters, and view observers Assuming the view survives forever
onStart() / onResume() Enter visible or interactive use Refresh transient UI and resume interaction Repeating expensive initialisation
onPause() / onStop() Lose focus or visibility Persist lightweight state and pause work Releasing resources needed immediately
onDestroyView() Remove the Fragment’s view Clear binding and view-only references Treating the Fragment as fully destroyed
onDetach() Remove the host connection Clear Activity references and callbacks Calling methods on the old context

Lifecycle Callbacks At A Glance

onAttach() is the first callback in the usual Fragment lifecycle. The Fragment receives a Context, commonly the hosting Activity, and can verify that the Activity implements a required callback interface. This is a good place for dependency setup that does not require widgets.

Next, onCreate() handles non-visual state. Read values from arguments, restore saved data, and prepare objects that can survive view recreation. The view is not available here, so calls such as findViewById() or access to a view binding belong later.

Attaching And Creating State

A Fragment may be attached to an Activity more than once during its lifetime. For example, Android can destroy the view during a configuration change and create a new one while retaining the Fragment instance. Code in onCreate() should therefore be safe to run once per Fragment instance, while view-specific code should be repeatable.

Arguments should be supplied with a factory method rather than by setting public fields. This allows Android to recreate the Fragment with predictable input:

companion object {
    fun newInstance(categoryId: Long) =
        ProductFragment().apply {
            arguments = bundleOf("category_id" to categoryId)
        }
}

Creating And Binding The View

onCreateView() inflates the XML layout and returns its root. In Kotlin, View Binding is commonly stored in a private nullable property and exposed through a guarded getter. The property must be cleared in onDestroyView(), because the Fragment can outlive the view hierarchy.

onViewCreated() is the practical home for RecyclerView or ListView adapters, click listeners, text watchers, and view lifecycle observers. A tutorial on ListView click handling is especially useful here, because item listeners should be attached after the list view and its adapter are ready.

Visible And Interactive States

onStart() means the Fragment is visible, although it may not yet have input focus. onResume() indicates that it is in the foreground and ready for interaction. Use these callbacks for short-lived work, such as restarting a camera preview, checking a permission-dependent display, or refreshing information that can change while the screen is away.

Avoid launching duplicate requests every time onResume() runs. A user switching between Sydney train stations in an app may trigger several pauses and resumes in a short period. ViewModel, LiveData, or Flow can coordinate data loading while the view lifecycle controls collection.

Pausing, Stopping, And Saving State

onPause() runs when the Fragment is losing focus, while onStop() runs once it is no longer visible. Save small, immediate values such as a selected tab, search text, or scroll position using onSaveInstanceState() or a suitable state holder. Larger application data belongs in a repository or local database rather than a Bundle.

Android’s lifecycle-aware APIs reduce manual callback management. A coroutine can collect a Flow with viewLifecycleOwner.lifecycleScope, ensuring collection stops when the view is destroyed. This is valuable for apps used across Australia’s variable network conditions, where a screen may disappear before a response arrives.

A Fragment that displays customer information should also follow the Privacy Act 1988 and the Australian Privacy Principles. Do not casually place personal details in logs or saved state, particularly if the app targets a local business handling names, addresses, or payment-related information.

Destroying The View Safely

onDestroyView() is one of the most important callbacks for avoiding memory leaks. Clear View Binding, adapters that retain view references, and listeners tied to the old hierarchy. The Fragment object may remain in the back stack, but every widget from the previous layout should be considered invalid.

Useful cleanup checks include:

  • Set the binding property to null
  • Stop view-bound animations and callbacks
  • Remove observers registered against the wrong lifecycle
  • Cancel work that exists only for the current screen

A common error is placing all cleanup in onDestroy(). That callback may occur much later, leaving an old Activity or view tree referenced while the Fragment waits in the back stack. Use viewLifecycleOwner for UI observers and keep view references inside the view’s lifetime.

Detaching And Releasing References

onDetach() is called when the Fragment is no longer connected to its host Activity. Clear interface references, callback objects, and context-dependent resources here if they are stored as fields. Never assume that an Activity reference remains valid after detachment.

This stage is also useful for detecting incorrect ownership. If a Fragment needs to communicate with its Activity, prefer a shared ViewModel, Fragment Result API, or a small interface established in onAttach(). The Activity should own navigation, while the Fragment manages its own presentation.

Before shipping an Android app for the Australian market, check the lifecycle with rotation, backgrounding, split-screen mode, and navigation back-stack changes. A compact verification list can expose most problems:

  • Rotate during a database or network request
  • Navigate away before an image or list update finishes
  • Reopen the Fragment after returning from another Activity
  • Test on both a current phone and an older device

For hands-on Android project examples involving common UI and data patterns, practical Android projects can provide useful comparison points. The key principle remains consistent: attach host-dependent resources early, create UI only when the view exists, and release every view or context reference at the correct lifecycle boundary.