Skip to main content
Android Development with Kotlin
CHAPTER 15 Beginner

Fragments and Fragment Lifecycle

Updated: May 16, 2026
25 min read

# CHAPTER 15

Fragments and Fragment Lifecycle

1. Introduction

In the early days of Android, developers built applications by creating 50 different Activities and jumping between them using Intents. However, Activities are heavy, slow to load, and terrible for large screens (like iPads/Tablets) where you might want to show a List on the left and Details on the right simultaneously. To solve this, Google introduced Fragments. A Fragment is a lightweight, reusable chunk of User Interface that lives *inside* an Activity. In this chapter, we will master Fragments and the Fragment Lifecycle. We will explore the modern "Single-Activity Architecture," learn how to dynamically swap UI chunks using the FragmentManager, and analyze the unique Lifecycle of a Fragment.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Explain the architectural difference between an Activity and a Fragment.
  • Understand the paradigm of Single-Activity Architecture (SAA).
  • Create a reusable Fragment and its associated XML layout.
  • Dynamically add, replace, and remove Fragments utilizing the FragmentManager.
  • Navigate the complexities of the Fragment Lifecycle (specifically onCreateView).

3. Fragments vs Activities

  • Activity: The heavyweight Window. An app must have at least one Activity. It is an independent entity registered in the Manifest.
  • Fragment: A lightweight UI module. It is NOT registered in the Manifest. It cannot exist on its own; it must be hosted inside an Activity.

*Analogy:* The Activity is the television set. The Fragments are the different channels you swap out on the screen.

4. Single-Activity Architecture (SAA)

Today, Google strictly recommends Single-Activity Architecture. Instead of having a HomeActivity, SearchActivity, and ProfileActivity, modern apps use a single MainActivity. This Activity holds a "Bottom Navigation Bar" and a blank FrameLayout in the center of the screen. When the user taps the "Search" tab, the code simply injects the SearchFragment into that blank space. It is blazingly fast and incredibly smooth.

5. Creating a Fragment

Creating a Fragment requires two pieces, just like an Activity: the Kotlin class and the XML layout.

The XML (fragment_home.xml):

xml
12345678910111213
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#E3F2FD">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Welcome to the Home Fragment!"
        android:layout_gravity="center"
        android:textSize="24sp" />

</FrameLayout>

The Kotlin (HomeFragment.kt): Fragments do not use onCreate() to set their layout. They use a special lifecycle method called onCreateView.

kotlin
12345678910111213141516171819
package com.example.fragmentdemo

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment

class HomeFragment : Fragment() {

    // This is where the Fragment inflates (draws) its XML layout!
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_home, container, false)
    }
}

6. The FragmentManager (Swapping Fragments)

How do we get the HomeFragment to actually appear inside our MainActivity? First, the activity_main.xml must have a blank container ready to hold it:
xml
1234
<FrameLayout
    android:id="@+id/fragmentContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

Next, in MainActivity.kt, we use the supportFragmentManager to execute a Fragment Transaction.

kotlin
123456789101112
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // 1. Instantiate the Fragment
    val homeFragment = HomeFragment()

    // 2. Begin the Transaction!
    supportFragmentManager.beginTransaction()
        .replace(R.id.fragmentContainer, homeFragment) // Swap the container with the Fragment
        .commit() // Execute the command!
}

7. The Fragment Lifecycle

Because a Fragment lives inside an Activity, its lifecycle is tied to the host Activity, but it has extra steps related to drawing its UI.
  • onAttach(): The Fragment attaches to the Activity.
  • onCreate(): The Fragment is created (but not the UI).
  • onCreateView(): The XML is inflated and the UI is drawn!
  • onViewCreated(): The UI is ready. This is where you should put your findViewById logic!
  • onResume(): The Fragment is actively running.
  • onDestroyView(): The UI is destroyed (but the Fragment logic stays alive in memory).
  • onDetach(): The Fragment is completely disconnected from the Activity.

8. Handling UI Logic in a Fragment (onViewCreated)

In an Activity, you use findViewById directly in onCreate. In a Fragment, you must wait until the view is fully created, and execute logic inside onViewCreated.
kotlin
12345678910
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    // Notice we must call 'view.findViewById' because the view holds the components!
    val myButton = view.findViewById<Button>(R.id.actionButton)
    
    myButton.setOnClickListener {
        println("Fragment Button Clicked!")
    }
}

9. Common Mistakes

  • Crashing requireActivity(): Fragments often need to ask their host Activity for information. If you call requireActivity() while the Fragment is in the background or completely detached, the app will instantly crash with an IllegalStateException. Always ensure the Fragment is isAdded before communicating with the host Activity.
  • Memory Leaks with ViewBinding: If you use modern ViewBinding in a Fragment, you MUST set the binding variable to null inside the onDestroyView() callback. Unlike Activities, Fragments can outlive their visual views. If you hold onto the visual references, you cause a massive memory leak!

10. Best Practices

  • Never Communicate Fragment to Fragment directly: If Fragment A needs to tell Fragment B something, do not try to link them directly. Fragment A should pass the data to the shared ViewModel (or the host Activity), and Fragment B should observe that shared ViewModel. This keeps modules perfectly decoupled.

11. Exercises

  1. 1. Create a blank Fragment class named ProfileFragment and its corresponding XML layout.
  1. 2. Write the Kotlin transaction code in MainActivity to .replace() the fragment container with your new ProfileFragment.

12. Coding Challenges

Challenge: Modify the MainActivity. Add two Buttons at the top of the screen ("Home" and "Profile"). Below the buttons, place the fragmentContainer. Write click listeners for both buttons. When "Home" is clicked, trigger a transaction to load HomeFragment. When "Profile" is clicked, trigger a transaction to load ProfileFragment. You have just built a custom Navigation Tab system!

13. MCQ Quiz with Answers

Question 1

In modern Android architecture, what is the explicit functional paradigm of Single-Activity Architecture (SAA)?

Question 2

Within the Fragment Lifecycle, which specific callback function must be utilized to programmatically inflate the associated XML layout file (drawing the UI)?

14. Interview Questions

  • Q: Explain the structural decoupling benefits of utilizing Fragments over monolithic Activities. How does this architecture specifically benefit tablet/foldable UI optimizations?
  • Q: Describe the execution sequence of the FragmentManager. Why must a Fragment transition be finalized with the .commit() command?
  • Q: Contrast onCreateView() with onViewCreated(). Why is executing findViewById operations strictly relegated to onViewCreated() rather than onCreateView()?

15. FAQs

Q: I used supportFragmentManager.beginTransaction().add() instead of .replace(). Now my fragments are overlapping and I can see both of them! Why? A: .add() literally stacks the new Fragment on top of the old one in the container (making it a transparent layer on top). .replace() completely destroys the old Fragment's view before injecting the new one. Always use .replace() for standard screen navigation!

16. Summary

In Chapter 15, we revolutionized our application structure by adopting modern Single-Activity Architecture (SAA). We isolated complex UI blocks into modular, lightweight Fragments, decoupling our presentation layer from heavyweight OS window constraints. We mastered the orchestration of these components, executing dynamic injection and extraction via the FragmentManager transaction API. Finally, we navigated the nuanced Fragment Lifecycle, ensuring strict architectural safety by isolating view binding logic to the onViewCreated execution phase.

17. Next Chapter Recommendation

Our modular navigation is fully operational. We can route users to beautiful screens. But those screens lack complex data entry. Proceed to Chapter 16: User Input, Forms, and Validation to learn how to securely capture and validate user data.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·