DEV Community

Cover image for Compose 1.13 beta is out. Three things in it actually matter to a solo developer.
Artem Garazha
Artem Garazha

Posted on

Compose 1.13 beta is out. Three things in it actually matter to a solo developer.

Jetpack Compose 1.13.0-beta01 shipped on October 7th. I read the release notes the way I always do: skim the commit log, click the issue tracker links, and try to figure out what's going to bite me when stable lands. I'm Artem Garazha, an Android developer from Ukraine, and I maintain a few side apps on my own. For me, "just bump the version" has never meant what it sounds like.

Most of the notes are noise. A few changes actually matter whether you adopt the beta or not. Here's what I'd want to know if I only had five minutes.

Kotlin 2.2 becomes a hard floor

The headline change: Compose 1.13 libraries now target Kotlin 2.2 and require kotlinc 2.2 as the minimum compiler.

If you track Kotlin releases anyway, this is nothing. If you're like me, though, you have an app sitting on Kotlin 2.0 or 2.1 because it compiles and shipping beats upgrading. This beta is the early warning. The moment 1.13 goes stable, that older Kotlin runtime stops being a valid setup.

There's also a build-file wrinkle. For a while now the recommended path has been the Compose Compiler Gradle plugin, which makes the Kotlin version explicit through your plugin version. If you never migrated away from the older composeOptions { kotlinCompilerExtensionVersion = "..." } block, you might need to restructure your build.gradle before you can even attempt the Kotlin 2.2 bump. Google's Compose-to-Kotlin compatibility map is worth a glance before you start editing.

I found this out the annoying way a few versions back when a "simple" Compose upgrade turned into an hour of Gradle archaeology. The symptom was cryptic: Gradle complaining about compiler versions in a language barely resembling a real error. Let me spare you that particular afternoon.

The practical advice: bump Kotlin first, on its own, and get a clean build. Then move the Compose dependency. Doing both in one shot makes it impossible to tell which one broke the build.

A recomposition bug that's been eating frames silently

This is the one I keep thinking about. The release notes describe it in one dry line:

Fixed a bug where passing Float.NaN or Double.NaN into a @Composable function would prevent that function from ever skipping recomposition, even when all arguments are unchanged.

The part that makes it land: Dp.Unspecified is backed by Float.NaN.

So if you ever passed Dp.Unspecified into a composable, directly or through something like Modifier.size(width = Dp.Unspecified, height = 24.dp), that composable would recompose on every single frame, forever. Compose decides whether to skip by comparing arguments. NaN never equals NaN, so the comparison always failed, and the recomposition always fired.

Here's why this would have wrecked my evenings: there's no spike to find. A profiler shows a constant, elevated recomposition count with no obvious culprit. No single frame jumps out. Your list scrolls a little worse than it should, battery drains a bit faster, and you can't point at anything. This is the kind of bug a team can carry for a year without knowing.

If you want to see it for yourself, a composable that takes an optional size works:

@Composable
fun Label(text: String, width: Dp = Dp.Unspecified) {
    Text(text, modifier = Modifier.width(width))
}
Enter fullscreen mode Exit fullscreen mode

Call Label("x", width = 24.dp) and the arguments stay stable, so Compose skips. Call Label("x") and the default Dp.Unspecified (which is Float.NaN under the hood) fails the equality check, so it recomposes every frame. Before 1.13, that second case was permanent. You'd never see it in a layout inspector because nothing looks wrong.

The fix alone justifies running a debug build on the beta to see whether anything suddenly gets smoother.

computedStateOf now fails loudly instead of lying

This is a behavioral change that will break code, and I'm fine with it. The calculation block of computedStateOf is now enforced as read-only. Write to any state inside that block and it throws IllegalStateException.

Before, writing inside computedStateOf was wrong but it didn't crash. It produced those unpredictable invalidation cascades and subtle recomposition loops that are miserable to trace. Now the framework tells you, directly, where the bad code is.

If your app has been doing something weird after state updates and the profiler hasn't helped, there's a real chance this is it. The beta will point at the offender for you.

The rest, quickly

A handful of smaller changes round out the release:

  • CompositionObserver resolves once per pass now. Calling setObserver mid-composition defers to the next pass. Movable content insertion also reports onBeginComposition and onEndComposition.
  • A memory leak in LinkComposer got fixed. Movable content that moves around was keeping wrapper group slots alive. If you lean on movable content, this could give you back some memory.
  • lifecycle-runtime bumped to 2.10.0, which AGP 9.5.0-alpha04 and later need for their lint checks to run.
  • ComposeTracer supports off-main-thread use now.
  • An invalidation edge case in computedStateOf around SnapshotStateObserver was cleaned up.

None of these will make headlines. Collectively they're the kind of quiet hardening that keeps a framework shippable.

Should you jump on the beta?

If your project is small and you have an afternoon to spare, yes. Move to Kotlin 2.2, pull the beta, run your debug app, and watch for two signals. First, does anything recompose visibly less? Second, does anything throw IllegalStateException inside a computedStateOf? Both are good news, even the crash.

If your app is in production and you can't risk a beta compiler, you don't have to do anything yet. But read the notes so the Kotlin 2.2 requirement doesn't ambush you when stable drops.

The Compose team is moving fast. 1.12 stable was barely a month ago and we're at 1.13 beta already. I'm not complaining. The treadmill is just real for someone shipping alone.


I write about building and shipping Android apps solo. You can find my retro Android app demo on YouTube and follow me on Instagram.

Top comments (0)