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.
Open an offline first app and content appears instantly, served from a local database while a background sync quietly reconciles that database with the server. Now in Android works exactly this way: every screen reads…
Compose gives you smooth scrolling, but no scrollbar to go with it. A LazyColumn, LazyRow, or LazyVerticalGrid glides through its content, yet there is no thumb on the side telling you where you are, and no way to grab…
AI agents can now reason about a task, call tools, and hold a conversation. What they still cannot do well is show you a native screen. An agent that books a flight can describe the options in text, but it cannot hand…
The Jetpack Compose Mechanisms Quiz asks ten questions that look like everyday Compose code: a parameter that refuses to skip, an effect that reads a stale value, a modifier chain that lays out the wrong way. Each one…
Modern Android UI code collects flows. You wrap a collect in repeatOnLifecycle, or you call collectAsStateWithLifecycle in a composable, and the data stops flowing when the screen goes to the background and starts again…
Most Android developers reach for SavedStateHandle when they need a value to outlive process death, then move on. You inject it into a ViewModel, call get and set or getStateFlow, and the system restores the value after…
Jetpack Compose navigation is imperative code. A NavKey is declared in one file, an entry<Route> { Screen() } lambda wires it to a composable in another, and the actual transitions are backStack.add(...) calls buried…
Every Android developer talks to the main thread without thinking about what it is. You write Handler(Looper.getMainLooper()).post { textView.text = result } to jump back from a background thread, you hear "don't block…
Every Android developer uses Context constantly. You read LocalContext.current inside a composable, call getApplicationContext() to avoid leaking when you build an image loader or a DataStore, resolve a string with…
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…
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 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 Android developer has overridden onCreate(), onResume(), and onDestroy(). You write your initialization logic, register listeners, and clean up resources, trusting that the framework will call these methods at the…
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…
Every Android release build passes through R8, the whole-program optimizing compiler that shrinks, obfuscates, and optimizes your code before it ships to users. At the center of R8's decision-making are keep rules, the…
Android's ViewModel is one of the most widely used architecture components, yet its core survival mechanism remains a mystery to most developers. You annotate a class, call viewModels() in your Activity, and your state…
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…
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…
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…
Dependency Injection (DI) is a core software design pattern that promotes loose coupling and enhances the testability and scalability of applications. While powerful libraries like Hilt and Koin are the standard for…
R8 is the default code shrinker, optimizer, and obfuscator for Android applications. It plays a crucial role in reducing APK size and improving runtime performance. While R8 is designed to be a drop-in replacement for…
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.