Fragment 1.9.0 is sitting at RC01 right now, and while "release candidate for a library in maintenance mode" is not exactly a headline that gets hearts racing, there are three concrete changes in this release that affect how you work day to day — even if you've already migrated most screens to Compose. Because the reality is that Fragment doesn't just quietly die when you switch toolkits. It's embedded in how Activity hosts its UI, how Navigation handles back stacks, and how every AndroidFragment composable works inside your Compose screens. Which means changes here have downstream effects whether you're thinking about them or not.
1. fragment-ktx Is Gone — In a Good Way
The most impactful change landed in alpha01 back in June, contributed by Jake Wharton: the fragment-ktx artifact has been merged into the main fragment artifact. Every Kotlin extension that used to live in fragment-ktx — viewModels(), activityViewModels(), by viewModels { factory }, the fragmentManager extension properties, all of it — is now part of the base dependency.
In practical terms, if you were already depending on fragment-ktx, nothing breaks. The old artifact still exists as an empty compatibility shim, so your existing build.gradle.kts keeps compiling without errors. But you can simplify your dependency block:
// Before
implementation("androidx.fragment:fragment-ktx:1.8.x")
// After (1.9.0+)
implementation("androidx.fragment:fragment:1.9.0-rc01")
// fragment-ktx is now redundant — the artifact is empty
This matters more than it looks. Historically, "use the KTX variant" was advice you had to give new Android developers who just copy-pasted a Java-era tutorial and then wondered why their Kotlin delegate syntax didn't compile. That distinction goes away in 1.9. There's one artifact. If you're writing Kotlin (you are), it has everything.
If your project has both fragment and fragment-ktx in your dependency tree, you'll see Gradle deduplicate to the higher version. The merge also means one fewer artifact to keep in sync when updating — a small quality-of-life win across a codebase with many modules.
Migration action: On 1.9.0+, you can remove fragment-ktx from your build files without any code changes. The APIs are still there, just in the base artifact. Run ./gradlew :app:dependencies to confirm fragment-ktx resolves as an empty POM after the upgrade.
2. ContextAware on Fragment — Small API, Useful Pattern
Also in alpha01: Fragment now implements the ContextAware interface, which means you can attach a context-available listener directly on a Fragment instance without subclassing or lifecycle observation boilerplate.
val fragment = MyFragment()
fragment.addOnContextAvailableListener { context ->
// Runs as soon as the Fragment is attached to a host
// Safe to resolve Context-dependent resources here
}
parentFragmentManager.commit {
add(R.id.container, fragment)
}
The practical use case is initialization code that needs a Context but shouldn't run until the Fragment is actually attached — think setting up a NotificationManager, resolving a system service, or wiring up something from the application DI graph that needs application context to resolve. Before this, the cleanest option was overriding onAttach(). The listener pattern is cleaner when you're configuring a Fragment from outside its own class, which happens more than you'd think in coordinator patterns.
3. maxLifecycle for AndroidFragment — The Compose Pager Fix
This is the change most likely to directly affect you if you're in a hybrid Compose + Fragment codebase, and it came in alpha02 in July. The AndroidFragment composable — the bridge that lets you embed a legacy Fragment inside a Compose screen — now takes an optional maxLifecycle parameter.
@Composable
fun MyPagerScreen() {
HorizontalPager(state = pagerState) { page ->
when (page) {
0 -> AndroidFragment(
clazz = DashboardFragment::class,
maxLifecycle = Lifecycle.State.STARTED
)
1 -> AndroidFragment(
clazz = AnalyticsFragment::class,
maxLifecycle = Lifecycle.State.STARTED
)
}
}
}
Here's why this matters. Fragment lifecycle and Compose's pager-driven visibility don't naturally agree on when a Fragment is "in front of the user." In a HorizontalPager, the page at index 0 and the page at index 1 can both be composed simultaneously — one is on screen, the other is in the prefetch window. Without maxLifecycle, both Fragments would receive onResume(), which means both are "started" from the Fragment's perspective even when one is actually offscreen. That's a recipe for:
- Analytics events firing for invisible screens
- Video players auto-starting while the user is on a different tab
- Background polling or sensor subscriptions running unnecessarily
- Camera or location resources held by an offscreen Fragment
Setting maxLifecycle = Lifecycle.State.STARTED caps the Fragment's lifecycle at STARTED for all pages that aren't currently visible. Only the currently selected page gets promoted to RESUMED. The Fragment still exists and is composed, but it won't receive onResume() until it's actually in front of the user.
I've seen this exact bug in apps that use HorizontalPager for a tab-style navigation layout with legacy Fragment screens embedded per tab. The Musist library screen uses a tab pager to switch between albums, artists, and playlists — and if I'd embedded Fragments there instead of pure Compose, this is precisely the lifecycle leak I'd have had. The fix is one parameter now. It used to require manual setMaxLifecycle() calls through the FragmentManager, which is easy to get wrong under configuration changes.
Rule of thumb: If you're embedding Fragments inside a HorizontalPager, TabRow, or any container where multiple Fragments can be composed simultaneously, always set maxLifecycle = Lifecycle.State.STARTED on the offscreen ones. The Compose runtime will promote to RESUMED when the user navigates to that page.
4. System Tracing for Fragment Lifecycle Events
Fragment 1.9.0-alpha02 also wired Fragment's own lifecycle transitions into Jetpack Tracing 2.0. What this means concretely: if you have Tracing 2.0 in your dependency graph and capture a Perfetto trace during development, Fragment's lifecycle events — onCreate, onCreateView, onViewCreated, onStart, onResume, and their counterparts — now appear as labeled slices in the System Trace view.
This is not a capability you had before. Historically, you'd see the work being done inside these methods (Binder calls, measure/layout passes) but you'd have to correlate them back to Fragment lifecycle timing manually. Now the Fragment name and lifecycle event show up directly in the trace, which makes it substantially easier to answer questions like "why is this Activity's first visible frame slow" when the answer is "because HeavyFragment.onViewCreated is doing too much synchronous work."
For Nodat, where startup time was something I spent serious effort on (60% cold start reduction, as covered in this post), having Fragment lifecycle events annotated in the trace would have made attribution significantly faster. The optimization work was the same either way, but finding the bottleneck is the hard part — and annotated traces make that discovery meaningfully cheaper.
5. RC01 Fix: FragmentScenario and FragmentContainerView
The rc01 release is a focused bug fix: when using FragmentScenario.launchInContainer() in tests, the Fragment under test is now correctly placed inside a FragmentContainerView host instead of a generic View. This matters because FragmentContainerView is the recommended host for production Fragment transactions, and its behavior around back stack animations and predictive back is different from a plain ViewGroup. Tests written against a generic container could miss animation-related bugs that only surface when running against the real host type.
If you use FragmentScenario in your test suite — which you should if you're still writing Fragment tests — this is a quiet correctness fix that makes your test environment more representative of production. No action needed on your end beyond upgrading.
The Maintenance Mode Signal — What It Actually Means
Fragment 1.9.0 is officially in maintenance mode. The release notes say it plainly: critical fixes only, no new features planned. Google recommends Jetpack Compose for building Android UIs going forward.
This is the same trajectory Navigation 2.x is on — and it's worth understanding what it does and doesn't mean for your codebase.
What it doesn't mean: Fragment is not deprecated, not being removed, and not broken. It will continue to work exactly as it does today for the foreseeable future. The Android platform itself is built around the Activity/Fragment model. Navigation 3 runs on top of Compose but Fragments still power backstack management internally in many app patterns. The library will receive security and crash fixes. Your apps that use Fragments will not break.
What it does mean: New feature investment is going into Compose and Navigation3. If there's a Fragment capability you're waiting on — something that would require a new API — that API is probably not coming. The surface area is frozen at this point.
Practical guidance: For greenfield features and new screens, build in Compose. For existing Fragment-based screens, migrate when you touch them for other reasons — not as a dedicated migration effort with no other goal. Maintenance mode means the rate of change goes to near zero, which is actually a stable target for hybrid codebases in transition.
The pattern I've settled on across my own apps: anything that gets touched for a bug fix or feature addition gets migrated to Compose at the same time, since the rewrite cost is low when you're already in the file. Screens that haven't been touched in over a year are treated as stable Fragment screens with no urgency to move them. OnlyArabs, which I started fully in Jetpack Compose, has zero Fragment screens and that's clearly the direction new apps should take — but Musist has several Fragment screens that are working fine and not worth touching just to achieve architectural purity.
Upgrade Checklist
Here's what to do when you update to Fragment 1.9.0:
- Remove
fragment-ktxfrom your dependency declarations. It's an empty artifact now — you're carrying dead weight if it's still there explicitly. - Audit
AndroidFragmentusages inside pagers or tab containers. AddmaxLifecycle = Lifecycle.State.STARTEDto non-visible tabs to prevent lifecycle leaks. - Add Jetpack Tracing 2.0 to your debug build configuration if you haven't already. Fragment lifecycle events in Perfetto traces are now available for free — you don't want to miss that in your next performance investigation.
- Update test dependencies: bump
fragment-testingto 1.9.0-rc01 alongside the main artifact soFragmentScenariopicks up the container fix.
Fragment 1.9.0 is not a release that demands urgent attention. But it's a solid, focused release that resolves real sharp edges in the Fragment/Compose interop story — and the maintenance mode announcement is a useful signal for planning your migration timeline. The library is stable, well-understood, and not going anywhere. The question is just whether you're building new things on it, and the answer to that should increasingly be no.
No comments yet. Be the first to leave one!