Dispatch Issue # 10
Good Morning Friends. This is JetpackCompose.app’s Dispatch — the Android/Jetpack Compose newsletter that’s as gratifying as catching a green light at every intersection on your morning commute.
Hope your 2025 is off to a fantastic start. It’s a long weekend here in the US so I figured it was a good opportunity to show up in your inboxes with some fun content. This is Issue #10, and we’ve got a bunch of interesting things to talk about. So buckle up and let’s get rolling!
🎩 Insider Insight
In a previous issue of this newsletter, we spoke about the badass creator of SQLite. As a reminder, Room also uses SQLite under the hood. I recently stumbled on some fun facts about our beloved database engine so figured I should share some that stood out for me-
- Born on a Battleship - SQLite wasn't created in a fancy Silicon Valley office, but for a US Navy destroyer! When server downtime meant potential battlefield issues, Dr. Richard Hipp asked: "What if databases didn't need servers?" (And mobile developers have been thankful ever since! 🙏)
- There are over ONE TRILLION SQLite databases in active use - Yes, you read that right. That's more databases than there are stars in the galaxy! Every Android device you've ever developed for probably has dozens of them humming along.
- Open Source, Not Open Contribution - Contributing to SQLite is invite-only. Only after you are invited and have signed an affidavit dedicating your contribution to the public domain can you submit patches.
- SQLite takes backward compatibility very seriously - All releases of SQLite version 3 can read and write database files created by the very first SQLite 3 release. As it turns out, that first release of SQLite 3 was in the year 2004!! 20+ years of backward compatibility 🤯
- The Bug That Became a Feature - Here's a wild one: SQLite allows NULL values in PRIMARY KEY columns. This was actually a bug, but when it was discovered, so many databases were already in production that fixing it would break backward compatibility. The team's solution? They just... left it! (Though they did fix it in WITHOUT ROWID tables).
- Every line of code in SQLite has 600+ lines of test code!!! - Tests cover 100% of branches (and 100% MC/DC) of the library.
😆 Dev Delight
Professor Utonium would be proud 🧪
GUILTY 🙏🏻
🍾 Pop Quiz
Consider the following Kotlin function:
fun puzzle() {
return run { 42 }
}
This function compiles successfully, even though it seems to return an Int where a Unit is expected. But if we write:
fun puzzle() {
return 42 // Error: return type mismatch
}
It doesn't compile!!!
So, why does the first function compile without errors?
Hint: Think about how run and type inference work in Kotlin.
Find the answer in a section below ⬇️
🥂 Tipsy Tip
Smooth Animations with keyframesWithSpline
Looking to add buttery smooth animations to your Jetpack Compose app? Introducing keyframesWithSpline! Unlike the standard keyframes animation spec, keyframesWithSpline produces a natural, smooth curve—perfect for animating predefined X, Y coordinates.
What's the Big Deal?
When animating movements along a path, especially with non-linear motions, smoothness is key. Traditional keyframes can produce abrupt transitions between points. With keyframesWithSpline, you get a Monotone Cubic Hermite Spline interpolation, resulting in seamless animations 😵💫
But what the hell is Monotone Cubic Hermite Spline interpolation?
Here's a simpler way to think about it:
When you have a bunch of points (like X and Y coordinates) and you want to connect them with a smooth curve (instead of jagged straight lines), Monotone Cubic Hermite Spline interpolation is basically a “draw a smooth curve through all these points without any weird wiggles or overshoots” technique.
- "Monotone" means no dramatic, unintended dips or peaks. Think of a gentle hill rather than a roller coaster.
- "Cubic Hermite Spline" is just math-speak for a formula that guarantees the curve gently passes through each point in a smooth, continuous way.
Here's how one can use it:
val pathAnimation = keyframesWithSpline<Offset> {
durationMillis = 2000
Offset(0f, 0f) at 0 // Starting point
Offset(100f, 200f) at 500
Offset(200f, 100f) at 1000
Offset(300f, 300f) at 1500
Offset(400f, 0f) at 2000 // Ending point
}
val position by animateValueAsState(
targetValue = ...,
animationSpec = pathAnimation
)
🔦 Community Spotlight
Have you ever wrestled with the order of Modifiers in Jetpack Compose? You’re not alone! Modifier ordering can sometimes lead to unexpected UI results.
Marcin Moskala has crafted a fun game called Modifier Order Guesser to help you sharpen your intuition about Modifiers.
Here’s how it works - you're presented with a snippet of code that leverages Modifiers and are also presented two components that potentially represent the output of the code snippet. Your job is to pick the right option out of the two. Great way to pass some time and wrap your heads around Modifier ordering.
💡 If your team meets regularly to talk Android, this game could be a fun segment in one of those meetings!
🥷 Featured Developer
I’d like to amplify a really talented Android community member, Rivu Chakraborty, who’s looking for his next role. He’s India’s very first GDE and has worked at companies like Viacom18, Meesho, Gojek, Paytm, BYJU’s, etc. He’s trying to relocate his family so if you or your company are hiring in Europe, kindly reach out to him directly 🙏🏻
🍾 Pop Quiz: Solution
// Compiles successfully
fun puzzle() {
return run { 42 }
}
// Doesn't compile
fun puzzle() {
return 42 // Error: return type mismatch
}
// Why??
In Kotlin, if a function doesn't explicitly declare a return type, it defaults to returning Unit. When you use run, its return type is inferred from the context. Since puzzle()
is expected to return Unit, run is inferred as run<Unit> { 42 }
.
Moreover, for Unit-returning lambdas, the last expression isn't treated as the return value. So, run { 42 }
effectively does nothing significant and returns Unit, satisfying the function's expected return type.
It is a crucial feature of the Kotlin language which makes its easy to work with lambdas in practical cases. This feature is actually called "Coercion to Unit" in the Kotlin language specification.
🦄 How you can help?
👉🏻 If you enjoyed this newsletter, I'd greatly appreciate it if you could share it with your peers and friends. Your support helps me reach more Android developers and grow our community. Writing this newsletter takes time and effort, and it truly makes my day when I see it shared within your network. Consider tweeting about it or sharing it in your team's Slack workspace. Thank you!
👉🏻 If you find this newsletter or any of my other free websites or open source contributions useful, consider supporting my work 🙏🏻
👉🏻 Get my Maker OS Notion Template that I use to run my life on Notion. If you are into productivity, you will appreciate it! Here’s a quick preview of what it looks like—
On that note, here’s hoping that your bugs are minor and your compilations are error free.