JetpackCompose.app
jetpackcomposeapp.bsky.social
JetpackCompose.app
@jetpackcomposeapp.bsky.social
The #1 destination for all things Jetpack Compose. Keeping up with Android Development is hard. We make it easy, entertaining and rewarding.

World class Android Developers read our newsletter to remain sharp 👉🏻 https://www.jetpackcompose.app/newsletter
We cover more Android tips like these in Dispatch, our newsletter that thousands of the best Android engineers diligently read 🚀

www.jetpackcompose.app/newsletter
November 11, 2025 at 4:51 PM
This leverages Google's Accessibility Test Framework (ATF) to catch:

❌ Missing content descriptions
❌ Insufficient touch target sizes
❌ Contrast problems

All during your regular UI tests.

Add this to your test setup TODAY. Your users will thank you.
November 11, 2025 at 4:51 PM
If you're still using onGloballyPositioned for a lot of your use cases, it's time to reconsider.

Your scroll performance will thank you.

We cover more Android tips like these in Dispatch, our newsletter that thousands of Android engineers diligently read 🚀

www.jetpackcompose.app/newsletter
November 9, 2025 at 6:49 PM
This is going to be a key building block for higher-level impression logging abstractions built on this in Compose 1.9.

Basically every scaled app needs visibility tracking. This single modifier is a must-know and will enable those easier-to-use Modifiers.
November 9, 2025 at 6:49 PM
Why it's better:

✅ Built-in debouncing & throttling
✅ Designed for visibility tracking
✅ Way more efficient for LazyColumn use cases
✅ Only fires on actual position/size changes

Perfect for impression tracking, triggering animations based on scroll position, etc.
November 9, 2025 at 6:49 PM
Enter Modifier.onLayoutRectChanged:
November 9, 2025 at 6:49 PM
Remember onGloballyPositioned? Powerful but overkill. It fires CONSTANTLY, especially in lazy lists.

If you're using it for visibility tracking or impression logging, you're probably tanking your scroll performance.
November 9, 2025 at 6:49 PM
If you like getting useful content like this, consider subscribing to our newsletter. We go to great lengths to add value each time you open our email. It shows up once every couple weeks so it's not hard to keep up.

www.jetpackcompose.app/newsletter
November 8, 2025 at 4:36 PM
When we discovered this, this sounds really obvious. However, I don't think most people realize that you can take it to the extreme where 99% of the code of your public facing java sdk is being written in Kotlin.

Simply incredible 👏🏻
November 8, 2025 at 4:36 PM
Why? Kotlin's interoperability is so good that the generated bytecode is indistinguishable from Java.

But the development experience is light-years ahead.

This is actually a common practice for library maintainers who have the (mis)fortune of maintaining Java libraries.
November 8, 2025 at 4:36 PM
Should you switch? If you're:

👉 Starting a new project
👉 Dealing with slow build times
👉 Frustrated with DI debugging

Metro deserves serious consideration. It's multiplatform-ready and has excellent IDE integration.

Check it out - github.com/ZacSweers/me...
GitHub - ZacSweers/metro: A multiplatform, compile-time dependency injection framework for Kotlin
A multiplatform, compile-time dependency injection framework for Kotlin - ZacSweers/metro
github.com
November 7, 2025 at 7:13 PM
What impresses us most: Square didn't just adopt Metro - they contributed back to it.

This is open source at its finest. One dev solves a problem well enough that a $44B company changes direction
November 7, 2025 at 7:13 PM
The performance wins:

ABI changes: 47% faster
Non-ABI changes: 56% faster
Clean builds: 25-28% faster

But speed isn't everything. Error messages are clearer because it's ONE framework, not three tools fighting each other.
November 7, 2025 at 7:13 PM
@zacsweers.dev built Metro as a personal project. It's a pure Kotlin compiler plugin (no KAPT, no KSP) that unifies the best parts of Dagger, Anvil, and kotlin-inject.

Square evaluated it, migrated internal apps, ran benchmarks, and said "we're switching."
November 7, 2025 at 7:13 PM
Built by long-time Dispatch reader @sebaslogen.bsky.social. This is the kind of problem-solving our community excels at.

If you've ever felt frustrated by ViewModel scoping limitations in Compose, give Resaca a try. - github.com/sebaslogen/r...
GitHub - sebaslogen/resaca: Compose Multiplatform library to scope ViewModels to a Composable, surviving configuration changes and navigation
Compose Multiplatform library to scope ViewModels to a Composable, surviving configuration changes and navigation - sebaslogen/resaca
github.com
November 5, 2025 at 5:39 PM
Even better: Built-in DI support (Hilt & Koin extensions) and works across all Compose Multiplatform targets.

Plus it's Chris Banes approved, which is basically a seal of quality in the Android world.
November 5, 2025 at 5:39 PM
Use cases are endless:

Dialog ViewModels that clean up when dismissed
LazyColumn items with their own business logic
Reusable components with isolated state
Multi-pager screens with per-page ViewModels
November 5, 2025 at 5:39 PM
The magic? This ViewModel:

✅ Survives configuration changes
✅ Survives navigation to backstack
✅ Survives recomposition
❌ Gets cleaned up when truly no longer needed

It's like remember + viewModel() had a baby with good cleanup hygiene.
November 5, 2025 at 5:39 PM