Fragments
๐งฉ Fragments
๐ผ๏ธ What a Fragment Is, and Why It Exists
An Activity represents a full screen; a Fragment represents a portion of one, with its own layout and its own Kotlin class โ designed to be combined, swapped, and reused across different Activities or screen configurations (a tablet showing two Fragments side by side where a phone shows them one at a time, for instance).
Fragments vs Web Components
| React Component | Android Fragment | |
|---|---|---|
| Represents | A reusable piece of UI | A reusable piece of UI |
| Has its own lifecycle? | Yes (mount/update/unmount) | Yes, nested inside the host Activity's |
| Hosted by | A parent component / the DOM tree | An Activity (or another Fragment) |
| Swapped at runtime? | Via conditional rendering / router | Via FragmentManager transactions |
๐ The Fragment Lifecycle
A Fragment has its own set of lifecycle callbacks, layered on top of (and driven by) its host Activity's lifecycle from Chapter 2:
onCreateView โ Inflate, Don't Configure
Inflates and returns the Fragment's layout โ the Fragment equivalent of an Activity's setContentView, except the View is returned rather than passed to a framework method.
onViewCreated โ Configure Here Instead
Called right after onCreateView, with the inflated View available as a parameter โ the right place to set up click listeners, bind data, and generally do what Chapter 2's Activity onCreate did, but for a Fragment's Views specifically.
This is the trap that catches most beginners: a Fragment instance can survive (e.g. kept on a back stack) while its View is torn down and later recreated โ onDestroyView fires without onDestroy. Holding a View reference in a regular property beyond onDestroyView is a classic memory-leak/crash source; view binding references (Chapter 3) should be nulled out in onDestroyView in real production code โ simplified away here to keep the examples focused, but worth knowing exists.
๐๏ธ FragmentManager โ Adding & Swapping Fragments
An Activity's layout reserves a container (a FrameLayout, typically), and the FragmentManager adds, replaces, or removes Fragments inside it at runtime:
The if (savedInstanceState == null) check matters: without it, rotating the device (Chapter 2) would re-add a duplicate Fragment on top of the one the FragmentManager already automatically restored. replace(...) swaps out whatever Fragment currently occupies that container for a new one โ add(...) stacks a new one on top instead, without removing what's there.
Manually calling supportFragmentManager.beginTransaction()... is genuinely how Fragment swapping works underneath, but next chapter's Navigation Component provides a higher-level, declarative way to manage Fragment navigation (a nav graph, back stack handling, and passing arguments all handled for you) that most real apps use instead. Understanding the manual mechanism first is what makes the Navigation Component feel like a natural upgrade rather than unexplained magic.
๐ข Talking Back to the Host Activity
A Fragment shouldn't hold a hard reference to a specific Activity class (that would defeat its whole reusability point) โ the standard pattern is an interface the Fragment defines and the hosting Activity implements:
context as? ProfileListener is a safe cast (Kotlin Fundamentals Chapter 3's ?./?: family, applied to a cast rather than a call) โ it yields null instead of crashing if the hosting Activity doesn't implement the interface, which the following listener?.onProfileSaved(...) then handles gracefully by simply doing nothing.
The interface-callback pattern above is the traditional approach and worth knowing, but modern Android code increasingly favors a shared ViewModel (scoped to the Activity, accessible from every hosted Fragment) for cross-Fragment communication instead โ covered fully once ViewModels are introduced in Course 2. Both solve the same underlying problem; the interface pattern is the more foundational one to understand first.
๐ป Coding Challenges
Challenge 1: A Basic Fragment
Create a WelcomeFragment with a simple layout (one TextView), implementing onCreateView. Add a FrameLayout container to MainActivity's layout, and load WelcomeFragment into it via FragmentManager in onCreate, guarded by the savedInstanceState null check.
Goal: Practice the basic Fragment creation and FragmentManager loading pattern.
Challenge 2: Swapping Fragments
Create a second Fragment, DetailsFragment, and add a Button to WelcomeFragment that, when clicked, uses FragmentManager to replace WelcomeFragment with DetailsFragment in the same container.
Goal: Practice replace() for swapping Fragments at runtime, not just loading one initially.
Challenge 3: Fragment-to-Activity Communication
Add an interface OnDetailsClosedListener with a function onDetailsClosed() to DetailsFragment, implement it via onAttach with a safe cast, and add a "Close" button that calls it. Have MainActivity implement the interface and log a message when it's called.
Goal: Practice the full interface-callback communication pattern end to end.
Compared to an Activity, a Fragment involves more moving pieces (its own lifecycle, a hosting container, a manager to add/remove it) for what's conceptually "just a reusable piece of UI." That overhead pays for itself once an app has several screens sharing common pieces, or needs different screen arrangements on different device sizes โ exactly the kind of reuse a single-Activity design can't offer on its own.
๐ฏ What's Next
Next chapter: Navigation Component โ the nav graph, SafeArgs, deep links, and back stack management, building directly on this chapter's Fragments.