Anil Sai
Anil Sai
Android Developer

πŸ“‘ Android Fragment Lifecycle Guide

πŸ“‘ Android Fragment Lifecycle Guide

πŸ” Mastering the Android Fragment Lifecycle: Modern Tips & Kotlin Code Examples

Fragments are essential for building modular and reusable UI components in Android. But with this power comes complexity β€” especially when managing the Fragment Lifecycle, which has some key differences from the Activity lifecycle.

In this guide, we’ll explore each stage of the Fragment lifecycle, provide Kotlin code examples, and share modern development tips so you can avoid common pitfalls and write cleaner, more robust code.


🧩 Fragment Lifecycle Overview

A Fragment has two primary lifecycles:

  • Fragment lifecycle: Deals with the fragment instance itself.
  • View lifecycle: Deals with the UI (View) of the fragment.

These lifecycles don’t always move together β€” and that’s why developers often hit bugs with view bindings and lifecycle observers.


πŸ”„ Fragment Lifecycle Flow (Visual)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
onAttach()
   ↓
onCreate()
   ↓
onCreateView()
   ↓
onViewCreated()
   ↓
onStart()
   ↓
onResume()
   ↓
-- Fragment Running --
   ↑
onPause()
   ↑
onStop()
   ↑
onDestroyView()
   ↑
onDestroy()
   ↑
onDetach()

🧠 Lifecycle Callbacks (with Kotlin Examples)

1️⃣ onAttach(context: Context)

1
2
3
4
override fun onAttach(context: Context) {
    super.onAttach(context)
    Log.d("Lifecycle", "onAttach")
}

βœ… Use this for getting context references, initializing callbacks or listeners tied to the host activity.


2️⃣ onCreate(savedInstanceState: Bundle?)

1
2
3
4
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    Log.d("Lifecycle", "onCreate")
}

βœ… Use this for initializing ViewModels, arguments, or non-UI data.


3️⃣ onCreateView(...)

1
2
3
4
5
6
7
override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    return inflater.inflate(R.layout.fragment_sample, container, false)
}

βœ… Avoid accessing views here. Just inflate and return the view.


4️⃣ onViewCreated(view: View, savedInstanceState: Bundle?)

1
2
3
4
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    Log.d("Lifecycle", "onViewCreated")
}

βœ… Use this for binding views, setting up adapters, and observing LiveData.


5️⃣ onStart() and onResume()

1
2
3
4
5
6
7
8
9
override fun onStart() {
    super.onStart()
    Log.d("Lifecycle", "onStart")
}

override fun onResume() {
    super.onResume()
    Log.d("Lifecycle", "onResume")
}

βœ… Use for analytics, media, sensors, or UI updates.


6️⃣ onPause() and onStop()

1
2
3
4
5
6
7
8
9
override fun onPause() {
    super.onPause()
    Log.d("Lifecycle", "onPause")
}

override fun onStop() {
    super.onStop()
    Log.d("Lifecycle", "onStop")
}

βœ… Use for pausing media and saving state.


7️⃣ onDestroyView()

1
2
3
4
override fun onDestroyView() {
    super.onDestroyView()
    Log.d("Lifecycle", "onDestroyView")
}

βœ… Nullify view binding and release UI resources here.


8️⃣ onDestroy() and onDetach()

1
2
3
4
5
6
7
8
9
override fun onDestroy() {
    super.onDestroy()
    Log.d("Lifecycle", "onDestroy")
}

override fun onDetach() {
    super.onDetach()
    Log.d("Lifecycle", "onDetach")
}

βœ… Clean up tasks and references to avoid memory leaks.


πŸ“¦ Full Fragment Lifecycle Example (Kotlin)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class SampleFragment : Fragment(R.layout.fragment_sample) {

    override fun onAttach(context: Context) {
        super.onAttach(context)
        Log.d("Lifecycle", "onAttach")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d("Lifecycle", "onCreate")
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Log.d("Lifecycle", "onViewCreated")
    }

    override fun onStart() {
        super.onStart()
        Log.d("Lifecycle", "onStart")
    }

    override fun onResume() {
        super.onResume()
        Log.d("Lifecycle", "onResume")
    }

    override fun onPause() {
        super.onPause()
        Log.d("Lifecycle", "onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.d("Lifecycle", "onStop")
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.d("Lifecycle", "onDestroyView")
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d("Lifecycle", "onDestroy")
    }

    override fun onDetach() {
        super.onDetach()
        Log.d("Lifecycle", "onDetach")
    }
}

πŸ§™β€β™‚οΈ Tips & Tricks for Modern Fragment Development

βœ… 1. Safe ViewBinding

1
2
3
4
5
6
7
8
9
10
11
private var _binding: FragmentSampleBinding? = null
private val binding get() = _binding!!

override fun onCreateView(...) = FragmentSampleBinding.inflate(inflater, container, false).also {
    _binding = it
}.root

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

βœ… 2. Share Data with ViewModel

1
private val sharedViewModel: SharedViewModel by activityViewModels()

βœ… 3. Use Lifecycle-Aware Observers

1
2
3
4
5
6
7
viewLifecycleOwner.lifecycleScope.launch {
    repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.stateFlow.collect {
            // UI updates
        }
    }
}

βœ… 4. Don’t Store Fragments in Static Fields

Instead, use:

1
2
3
supportFragmentManager.beginTransaction()
    .replace(R.id.container, MyFragment())
    .commit()

🧠 Conclusion

Master the Fragment lifecycle to create high-performance, maintainable, and bug-free apps. Separate UI and business logic, use ViewModel, and always clean up bindings to avoid leaks.

comments powered by Disqus