Blog Infos
Author
Published
Topics
, , , ,
Published

Run non-Composable logic after every successful recomposition

credits : https://unsplash.com/

 

Introduction
  • In Jetpack ComposeSideEffect is a special block you use when you want to do something after your UI has been drawn. It gives us a set of tools to safely handle such side effects, and one of the simplest is called SideEffect
Why we need SideEffect?
  • In Jetpack Compose, UI is built using pure functions — they take input (state) and return UI (Composable functions). This makes Compose powerful and predictable.
  • But not everything in an app is pure. Sometimes, we need to interact with things outside the Composable world, like:
  1. Logging to Logcat
  2. Reading/writing from disk
  3. Updating a variable outside the UI and may more…
  • These actions are known as side effects because they affect the world outside the Composable function and don’t return a UI element.
  • As it gives us a set of tools to safely handle such side effects among them these 4 are the most commonly used by developers:
  1. LaunchedEffect
  2. rememberCoroutineScope
  3. DisposableEffect
  4. SideEffect
  • In this blog, we’ll primarily focus on SideEffect—why it’s needed and how it works internally. But before diving deep, let’s briefly explore the other three commonly used side-effect handlers in Jetpack Compose: LaunchedEffectrememberCoroutineScope, and DisposableEffect.
LaunchedEffect and rememberCoroutineScope
  • They both are used to handle the execution of suspend functions within a Composable.
  • When we use LaunchedEffect, Compose automatically launches the coroutine when the specified key or state changes. If the key changes again, the existing coroutine is cancelled and a new one is started.
  • rememberCoroutineScope is used in Jetpack Compose to get a stable CoroutineScope that stays the same across recompositions. This is particularly useful when you want to launch coroutines in response to user interactions, like button clicks or gestures.
  • Unlike LaunchedEffect, which is triggered automatically by changes in state or keys, rememberCoroutineScope is manually controlled — you decide when to launch a coroutine using the scope it provides. The important thing is that this scope is remembered and doesn’t get recreated every time the Composable recomposes.
  • This means you can safely call scope.launch { } without worrying about the scope being reset or causing unintended behavior due to recomposition. It helps avoid issues like launching duplicate coroutines or losing coroutine references during UI updates.
DisposableEffect
  • Used when you need to set up and clean up something (like a listener, callback, or subscription) based on a key. Think of it as Compose’s version of onStart() and onStop().

Both DisposableEffect and SideEffect are used to run non-suspending functions inside Composables. DisposableEffect is designed for setting up and cleaning up resources, such as listeners, and follows the lifecycle of the Composable.

SideEffect
  • SideEffect is a Composable Side Effect API that lets you execute a block of non-suspending code after every successful recomposition of a Composable.
  • This means once the UI has been updated and the Composable has finished rendering, SideEffect gives you a hook to run additional logic — but outside of the actual UI-building process.
  • Unlike LaunchedEffect, it doesn’t launch coroutines or deal with suspend functions. Instead, it’s perfect for those small actions that need to happen because of recomposition, but don’t directly affect the UI.
Where we use it?
  • 🔍 Logging : You can log whenever a Composable recomposes, which is great for debugging or understanding how often and why recomposition happens.

  • 📡 Triggering analytics: When a particular screen or UI state is shown, you might want to fire an analytics event. Since SideEffect runs after recomposition, it’s safe for such operations.
  • 🔄 Synchronizing state with non-Composable code: If you’re interacting with something outside of Compose (like shared preferences, global variables, or a legacy API), SideEffect ensures that you update them in sync with the latest Composable state — and without breaking Compose’s unidirectional data flow.

  • Every time ProfileScreen recomposes (e.g., userName changes), SideEffect is called. It writes the updated name to SharedPreferences safely after the composition is done. This avoids side effects during UI rendering and keeps your state in sync with non-Compose storage

SideEffectruns after every successful recomposition and is useful for tasks like logging or triggering analytics.

What Happens Internally When You Use SideEffect?
  • Now, let’s explore the internal working of SideEffect in Jetpack Compose and see what happens when we call this block of code.
  • When ProfileScreen(name = "Richa") is called inside a Compose hierarchy (e.g., inside setContent {}), the Compose runtime begins composition or recomposition.
  • Compose begins executing the function top to bottom and hit SideEffect{…}. The Log.d(...) will not run immediately
  • Inside the Compose runtime, SideEffect looks something like this:
  • The effect lambda (Log.d(...)) is stored in a side-effect buffer and Compose doesn’t execute it yet — it just registers it for later.
  • Then Compose proceeds to execute Text(“Hello $name!”) This part builds a node in the UI tree with the value "Hello Richa".After building or diffing the Composable UI tree this text appears on Screen.
  • Now comes the post-composition phase. Compose executes all recorded side effects, including the one you defined. Now “SideEffect: Recomposed with name: Richa” now your log gets printed.

It runs only after the Composable has successfully recomposed, ensuring your logs always capture the latest and most accurate UI state.

  • This is guaranteed to happen only after recomposition was successful, so your logs will always reflect the most accurate UI state.
  • Internally, Compose records the lambda using recordSideEffect(...). Once the recomposition successfully completes, the effect is executed exactly once per recomposition cycle.
Real UseCase Sample

  • This allows you to track how the screen state changes with every recomposition — a simple and powerful debugging technique.

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

,

Reimagining Android Dialogs with Jetpack Compose

Traditional Android dialogs are hard to test, easy to leak, and painful to customize — and in a world of Compose-first apps, they’re overdue for an upgrade.
Watch Video

Reimagining Android Dialogs with Jetpack Compose

Keith Abdulla
Staff Android Engineer, Design Systems
Block

Reimagining Android Dialogs with Jetpack Compose

Keith Abdulla
Staff Android Engine ...
Block

Reimagining Android Dialogs with Jetpack Compose

Keith Abdulla
Staff Android Engineer, D ...
Block

Jobs

Summary
  • We must be careful when introducing operations that interact with the outside world — like logging, analytics, or state syncing in Compose.
  • That’s where SideEffect shines it lets you safely perform side effects like logging after every successful recomposition.
  • Think of Compose as collecting side effects during UI composition and then executing them in a batch after the composition is finished.

Understanding how SideEffect works helps you write cleaner, more predictable Compose code—and debug UI behavior more effectively.

  • In the next blog, we’ll dive deep into the internal workings of LazyColumn and LazyRow in Jetpack Compose — exploring how they manage item rendering, recycling, and scroll state.
    We’ll also compare them with traditional Android views like RecyclerView to understand the performance differences and architectural improvements Compose brings.
  • Reference Link : https://developer.android.com/develop/ui/compose/side-effects

Till then if you found this helpful:

💬 Leave a comment if you’ve used SideEffect in a unique or interesting way.
👏 Clap if you learned something new about how Compose handles recomposition and side effects and share this blog with your fellow Android developers to spread the Compose knowledge!
Stay tuned — it’s going to be a fun ride into Compose internals!🙌

Take Care 🙂

This article was previously published on proandroiddev.com.

Menu