If you’re tired of repeating the same dependencies across different modules in your Android project, you’re not alone. Managing dependencies manually is error-prone, messy, and not scalable. Fortunately, Bundles in libs.versions.toml offer a clean and modern solution that saves time and reduces duplication. Let’s break it down, step by step, in a simple way. What...
Managing data on Android has evolved significantly over the years. From SharedPreferences to Room, we’ve seen the full spectrum. But when it comes to storing structured, complex data in a lightweight and efficient way, Proto DataStore steps in as a game-changer.
In this blog, we’ll walk through Proto DataStore, how it works under the hood, and how to use it with Protocol Buffers to store complex objects. We’ll also look at how it stacks up against the older SharedPreferences and why it’s the better modern choice.
Let’s break it down step by step.
What is Proto DataStore?
Proto DataStore is a Jetpack library from Google that helps you store typed objects persistently using Protocol Buffers (protobuf), a fast and efficient serialization format.
It’s:
Type-safe
Asynchronous
Corruption-resistant
Better than SharedPreferences
Unlike Preferences DataStore, which stores data in key-value pairs (similar to SharedPreferences), Proto DataStore is ideal for storing structured data models.
Why Use Proto DataStore?
Here’s why developers love Proto DataStore:
Strong typing — Your data models are generated and compiled, reducing runtime errors.
Speed — Protocol Buffers are faster and more compact than JSON or XML.
Safe and robust — Built-in corruption handling and data migration support.
Asynchronous API — Uses Kotlin coroutines and Flow, keeping your UI smooth.
Store Complex Objects with Proto DataStore
Let’s go hands-on. Suppose you want to save a user profile with fields like name, email, age, and preferences.
Avoid it for relational data (instead use Room) or for simple flags (Preferences DataStore may suffice).
Conclusion
Proto DataStore is the future-forward way to store structured data in Android apps. With Protocol Buffers at its core, it combines speed, safety, and type-safety into one clean package.
Whether you’re building a user profile system, app settings, or configuration storage, Proto DataStore helps you stay efficient and future-ready.
TL;DR
Q: What is Proto DataStore in Android? A: Proto DataStore is a modern Jetpack library that uses Protocol Buffers to store structured, type-safe data asynchronously and persistently.
Q: How do I store complex objects using Proto DataStore? A: Define a .proto schema, set up a serializer, initialize the DataStore, and read/write using Flow and coroutines.
Q: Why is Proto DataStore better than SharedPreferences? A: It’s type-safe, faster, handles corruption, and integrates with Kotlin coroutines.
If you’re still using SharedPreferences in your Android app, it’s time to move forward. Google introduced Jetpack DataStore as a modern, efficient, and fully asynchronous solution for storing key-value pairs and typed objects. In this blog, we’ll break down what Jetpack DataStore is, why it’s better than SharedPreferences, and how you can use it effectively...
Unit testing in Kotlin isn’t just about making sure your code works. It’s about writing tests that prove your code works, stays reliable over time, and catches bugs before they hit production. Google engineers treat testing as a core development skill, not an afterthought. And you can do the same. In this guide, we’ll break...
Room is one of the most popular persistence libraries for Android developers. It abstracts away a lot of boilerplate and gives us an easy way to work with SQLite. But when your app evolves and your database schema changes, you need to handle Room Database Migrations properly — or you risk losing your users’ data. This guide...
Jetpack Compose has completely changed how we build Android UIs. With its declarative approach, you just describe what your UI should look like, and Compose takes care of the rest. But here’s the thing: your app isn’t only about drawing screens. There are things like showing a toast, requesting a permission, or launching a background...
Jetpack Compose, Android’s modern UI toolkit, introduces a declarative approach to building user interfaces. With this shift comes a new way of thinking about side effects — operations that interact with the outside world or perform actions outside the scope of a composable function. Understanding how to manage these side effects properly is crucial to building reliable, efficient, and reactive Compose applications.
In this article, we’ll dive into three key APIs provided by Compose for handling side effects: SideEffect, LaunchedEffect, and DisposableEffect. Each serves a distinct purpose and understanding their differences can help you write cleaner, more predictable UI code.
What Are Side Effects in Jetpack Compose?
In Jetpack Compose, a side effect is any change that happens outside the scope of a composable function. This might include updating a database, logging analytics, showing a toast, or triggering a network call. Because composable functions can be re-executed (recomposed) frequently and unpredictably — whenever state or parameters change — running side-effect code directly inside them can lead to bugs or performance issues, such as duplicate network requests or inconsistent UI states.
Why Do We Need Side-Effect APIs in Jetpack Compose?
The declarative paradigm means you describe what the UI should look like, and Compose decides how and when to update it. However, this also means you can’t control exactly when your composable functions run. If you place side-effect code (like a network call) directly in a composable, it might run multiple times — once for every recomposition — which is usually not what you want.
Side-Effect APIs in Jetpack Compose are designed to solve this problem. They provide safe, predictable ways to perform actions that reach outside the Compose runtime, such as:
Triggering one-time operations
Cleaning up resources
Synchronizing Compose state with external systems
Key Side-Effect APIs in Jetpack Compose
Let’s explore the most commonly used Side-Effect APIs in Jetpack Compose, when to use each, and see them with simple code examples.
1. SideEffect
What it does:
Runs code after every successful recomposition of the parent composable.
When to use:
For actions that should happen every time the UI updates, like logging or updating analytics.
When you need to synchronize Compose state with an external system, but not for heavy or asynchronous operations.
Here, LaunchedEffect ensures the network call runs only when userId changes—not on every recomposition—preventing duplicate requests and wasted resources.
3. DisposableEffect
What it does:
Performs setup and cleanup logic tied to the lifecycle of the composable. Runs setup when the key(s) change, and cleanup when the composable leaves the composition.
When to use:
For managing resources like listeners, callbacks, or broadcast receivers that need explicit teardown.
When you want to perform cleanup when a composable is removed from the UI tree.
This ensures the observer is added when the composable enters the composition and removed when it leaves, preventing memory leaks.
Common Mistakes and How to Avoid Them
Running Expensive Operations in SideEffect: Avoid using SideEffect for network calls or other heavy operations—it runs on every recomposition, which can lead to performance issues and duplicate work.
Ignoring Cleanup: If you add listeners or callbacks, always use DisposableEffect to remove them when the composable is disposed.
Not Using Keys Properly: For LaunchedEffect and DisposableEffect, always specify appropriate keys to control when effects should re-run.
Choosing the Right Side-Effect API
Conclusion
Side-Effect APIs in Jetpack Compose are essential for bridging the gap between declarative UI and imperative side effects. By understanding and using SideEffect, LaunchedEffect, and DisposableEffect correctly, you can:
Prevent bugs and performance issues caused by unwanted repeated side effects
Build responsive, robust, and maintainable Compose apps
Ensure your app interacts safely with the outside world
Remember:
Use SideEffect for lightweight, repeatable actions after recomposition
Use LaunchedEffect for one-time or asynchronous tasks
Use DisposableEffect for managing resources with setup and teardown
Mastering these tools will help you write cleaner, more reliable Compose code — and take your Android apps to the next level.
Android Automotive OS is Google’s in‑car operating system that runs directly on a vehicle’s hardware. Not to be confused with Android Auto (a phone projection platform), Android Automotive OS Architecture is a complete software stack, ready for infotainment, driver assistance apps, and full vehicle integration. Let’s dive into its main layers. Android Automotive Architecture A...
If you’ve been working with Android and Fragments, you’ve probably faced this decision: should I use add() or replace() when switching Fragments? It might sound simple — but the difference between FragmentTransaction.add() and FragmentTransaction.replace() can lead to bugs, memory leaks, or even unexpected UI behavior if misunderstood. This guide breaks it down clearly and aligns with modern...
In the world of Android development, configuration changes are one of those things that often trip up even seasoned developers. You rotate your device, and suddenly your Activity is destroyed and recreated — poof! That counter you were tracking? Gone. Thankfully, Android ViewModel has your back. In this article, we’ll dive deep into how Android ViewModel survives...