Activity & Fragment Lifecycle (Internals)

📖 Concept

The Activity lifecycle is the most fundamental concept in Android development. At the senior level, you need to understand not just the callbacks, but the internal state machine that drives them.

Activity Lifecycle States & Transitions:

[DOES NOT EXIST]
     ↓ onCreate()
[CREATED] ──── onStart() ────→ [STARTED]
                                    ↓ onResume()
                               [RESUMED] (foreground, interactive)
                                    ↓ onPause()
                               [STARTED] (visible but not interactive)
                                    ↓ onStop()
                               [CREATED] (not visible)
                                    ↓ onDestroy()
                            [DOES NOT EXIST]

Internal working:

  • ActivityManagerService (AMS) in system_server process manages lifecycle transitions via Binder IPC
  • The TransactionExecutor in the app process receives lifecycle transactions and executes them in order
  • Each state transition is a ClientTransaction containing ActivityLifecycleItem callbacks
  • Config changes (rotation) trigger: onPause → onStop → onDestroy → onCreate → onStart → onResume

Fragment Lifecycle (additional complexity):

  • Fragments have their own lifecycle PLUS a view lifecycle (getViewLifecycleOwner)
  • Fragment lifecycle is managed by FragmentManager's state machine
  • Fragment view can be destroyed while Fragment instance lives (e.g., back stack)

Critical edge cases that cause production bugs:

  1. onSaveInstanceState timing — Called between onPause and onStop (pre-API 28) or after onStop (API 28+)
  2. Fragment transaction after onSaveInstanceState — IllegalStateException crash
  3. Activity recreation — ViewModel survives, but Activity/Fragment instances don't
  4. Multi-window mode — Both Activities can be in STARTED state, but only one is RESUMED

💻 Code Example

codeTap to expand ⛶
1// Lifecycle-aware component that handles edge cases
2
3// BAD: Leaks and crashes ❌
4class LeakyActivity : AppCompatActivity() {
5 private var networkCallback: NetworkCallback? = null
6
7 override fun onCreate(savedInstanceState: Bundle?) {
8 super.onCreate(savedInstanceState)
9 // This callback outlives the Activity on config change!
10 networkCallback = object : NetworkCallback() {
11 override fun onDataReceived(data: String) {
12 textView.text = data // Crash: textView may be null after destroy
13 }
14 }
15 NetworkManager.register(networkCallback!!)
16 }
17 // Missing: unregister in onDestroy → memory leak + crash
18}
19
20// GOOD: Lifecycle-aware, no leaks ✅
21class SafeActivity : AppCompatActivity() {
22 override fun onCreate(savedInstanceState: Bundle?) {
23 super.onCreate(savedInstanceState)
24
25 lifecycle.addObserver(object : DefaultLifecycleObserver {
26 override fun onStart(owner: LifecycleOwner) {
27 NetworkManager.register(callback)
28 }
29 override fun onStop(owner: LifecycleOwner) {
30 NetworkManager.unregister(callback)
31 }
32 })
33 }
34}
35
36// Fragment View Lifecycle — common source of bugs
37class MyFragment : Fragment(R.layout.my_fragment) {
38 private var _binding: MyFragmentBinding? = null
39 private val binding get() = _binding!!
40
41 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
42 super.onViewCreated(view, savedInstanceState)
43 _binding = MyFragmentBinding.bind(view)
44
45 // Use viewLifecycleOwner for UI observations, NOT this (fragment)
46 viewLifecycleOwner.lifecycleScope.launch {
47 viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
48 viewModel.uiState.collect { state -> binding.update(state) }
49 }
50 }
51 }
52
53 override fun onDestroyView() {
54 super.onDestroyView()
55 _binding = null // Prevent memory leak — view is destroyed but fragment lives
56 }
57}

🏋️ Practice Exercise

Practice:

  1. Draw the complete Activity lifecycle with all callbacks from memory
  2. What's the difference between onStop and onDestroy? When is onDestroy NOT called?
  3. Explain the Fragment view lifecycle vs Fragment lifecycle — why are they different?
  4. What happens to the lifecycle when a Dialog appears over your Activity?
  5. Write a lifecycle-aware component using DefaultLifecycleObserver
  6. Explain what happens during a configuration change — which objects survive?
  7. What is the difference between finish(), moveTaskToBack(), and System.exit()?

⚠️ Common Mistakes

  • Observing LiveData/Flow with Fragment's lifecycle instead of viewLifecycleOwner — causes duplicate observers after back stack navigation

  • Not nullifying view binding in onDestroyView — Fragment instance outlives its view on the back stack, causing memory leak

  • Committing FragmentTransactions after onSaveInstanceState — causes IllegalStateException, use commitAllowingStateLoss only as last resort

  • Assuming onDestroy is always called — it's NOT called when the system kills the process

  • Doing heavy work in onCreate — blocks the main thread, causes ANR if > 5 seconds

💼 Interview Questions

🎤 Mock Interview

Mock interview is powered by AI for Activity & Fragment Lifecycle (Internals). Login to unlock this feature.