Android & Kotlin Technical Articles
Detailed articles on Android development, Jetpack Compose internals, Kotlin coroutines, and open source library design by skydoves, Google Developer Expert and maintainer of Android libraries with 40M+ annual downloads. Read practical guides on Retrofit, Compose Preview, BottomSheet UI, coroutine compilation, and more.
This is a collection of private or subscriber-first articles written by the Dove Letter, skydoves (Jaewoong). These articles can be released somewhere like Medium in the future, but always they will be revealed for Dove Letter members first.
A growing catalog of self-contained Jetpack Compose animation walkthroughs covering animateAsState, AnimatedContent, AnimatedVisibility, Animatable, rememberInfiniteTransition, SharedTransitionLayout, gesture-driven motion, and Canvas particle systems — every constant tweakable live with Compose Hot Reload.
Every frame in a Compose application starts with a signal from the Android Choreographer. The Choreographer is the system component that schedules work to run in sync with the display's VSYNC pulse, ensuring that UI…
LazyColumn renders only the items that are visible on screen. Unlike a regular Column that composes every child upfront, LazyColumn defers composition until the layout phase, composes items on demand as they scroll into…
Compose's snapshotFlow converts snapshot state reads into a Kotlin Flow. Each call to snapshotFlow registers its own apply observer with the snapshot system, watching for state changes that should trigger new emissions.…
Strong Skipping Mode is one of the most misunderstood features in Jetpack Compose. A common belief is that enabling it makes all types stable, eliminating the need to think about stability entirely. This is wrong.…
Navigation 3 is a ground up redesign of Jetpack navigation for Compose. Unlike Navigation 2, which adapted the Fragment based navigation model to Compose through NavController and XML graph definitions, Navigation 3 is…
Compose's performance model centers on one idea: skip work that does not need to happen. When the runtime can prove that a composable's inputs have not changed, it skips re-execution entirely. This optimization, called…
Landscapist provides a composable image loading library for Jetpack Compose and Kotlin Multiplatform. Among its image composables, LandscapistImage stands out as the recommended choice: it uses Landscapist's own…
Every Compose app draws images. Whether you call Image(painterResource(R.drawable.photo)) to display a bitmap, render a Material icon with Icon(Icons.Default.Search), or load a vector drawable, the same underlying…
Every @Composable function you write produces invisible scaffolding. The Compose compiler wraps each Kotlin construct in a "group" that tells the runtime what it can do during recomposition. A conditional branch gets…
Every Android developer using Compose has written @Preview above a composable and watched it appear in the Studio design panel. But what actually happens between that annotation and the rendered pixels? The answer…
Jetpack Compose is a UI toolkit on the surface, but its internals draw from decades of computer science research. The runtime uses a data structure borrowed from text editors to store composition state. The modifier…
Every Compose developer has written remember { mutableStateOf(0) }. The value survives recomposition without any explicit storage reference. No ViewModel, no map, no key. Compose knows where the value belongs based on…
Jetpack Compose stores your entire composition tree in a data structure called the SlotTable. Every composable call, every remembered value, every key is recorded as groups and slots in this table. For years, the…
Jetpack Compose manages UI state through a system called Snapshots, a concept borrowed from database theory that enables isolated, concurrent access to shared mutable state. When you write var count by…
Jetpack Compose revolutionized Android UI development with its declarative approach, but what makes it truly powerful is the sophisticated machinery underneath. At the heart of Compose's reactivity lies the Snapshot…
Google Maps popularized a bottom sheet pattern that most Android developers recognize immediately: a small panel peeking from the bottom of the screen, expandable to a mid height for quick details, and draggable to full…
Jetpack Compose's stability system determines whether a composable function can be skipped during recomposition. When all parameters are stable, Compose can compare them and skip the function entirely if nothing…
Compose's derivedStateOf provides a way to create computed state that only triggers recomposition when the computed result actually changes. When you write val fullName by remember { derivedStateOf { "${firstName.value}…
Jetpack Compose manages UI state through a sophisticated identity system that determines when composables should be reused versus recreated. When you wrap content in key(userId) { UserCard(user) }, you're providing…
Jetpack Compose introduced a declarative paradigm for Android UI, but declarative doesn't mean stateless. User interactions create state like scroll positions, text field contents, and expanded sections that must…
Jetpack Compose's Modifier system has been the primary way to apply visual properties to composables. You chain modifiers like background(), padding(), and border() to build up the appearance and behavior of UI…
Jetpack Compose transforms declarative UI code into pixels on screen through a pipeline of three distinct phases: Composition, Layout, and Drawing. When you change a state variable, Compose doesn't redraw everything, it…
Building complex user interfaces in Jetpack Compose often requires going beyond the standard Box, Row, and Column layouts. While these composables handle most common scenarios beautifully, there are times when you need…
Jetpack Compose's declarative UI paradigm promises simplicity: you describe your UI as a function of state, and the framework handles updates automatically. But behind this elegant abstraction lies a sophisticated…
Jetpack Compose uses a smart recomposition system to optimize UI updates. At the heart of this optimization is stability inference - the compiler's ability to determine whether a type's values can change over time.…
Building dynamic user interfaces has long been a fundamental challenge in Android development. The traditional approach requires recompiling and redeploying the entire application whenever the UI needs to change—a…
Table of Contents Introduction Architecture Overview Core Modules hot-reload-agent hot-reload-orchestration hot-reload-runtime-jvm hot-reload-gradle-plugin hot-reload-core hot-reload-analysis The Hot Reload Flow…
A comprehensive study of how the Compose compiler determines type stability for recomposition optimization. Table of Contents Compose Compiler Stability Inference System Table of Contents Chapter 1: Foundations 1.1…
In Jetpack Compose, Crossfade provides a simple and declarative way to animate the transition between two different UI states. When the targetState passed to it changes, it smoothly fades out the old content while…
The derivedStateOf API in Jetpack Compose provides a convenient mechanism for creating memoized state that automatically updates when its underlying dependencies change. While essential for performance optimization in…
The SlotTable is the in-memory data structure that represents the UI tree of a Jetpack Compose application. Instead of a traditional tree of objects, it's a highly optimized, flat structure designed for extremely fast…
Google has recently launched the official runtime-annotation library, which serves a similar purpose to the community-built compose-stable-marker library. The idea behind compose stable markers originated from the…
The Jetpack Compose ecosystem has grown exponentially in recent years, and it is now widely adopted for building production-level UIs in Android applications. We can now say that Jetpack Compose is the future of Android…
Like what you see?
Subscribe to Dove Letter to get weekly insights about Android and Kotlin development, plus access to exclusive content and discussions.