Mobile Development 11 min read

Jetpack Compose Side Effects: LaunchedEffect, rememberCoroutineScope, SideEffect

The article explains what side effects are in functional and declarative UI programming, why managing them is crucial in Jetpack Compose, and provides detailed usage examples of the four main side‑effect APIs—LaunchedEffect, rememberCoroutineScope, SideEffect, and DisposableEffect—complete with code snippets and key considerations.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Jetpack Compose Side Effects: LaunchedEffect, rememberCoroutineScope, SideEffect

What Is a Side Effect?

In functional programming and declarative UI frameworks, a side effect refers to any operation performed by a function that goes beyond returning a result, such as modifying external state or interacting with system resources. In Jetpack Compose, side effects are actions executed inside a Composable that run on every recomposition rather than only on the first call, distinguishing them from imperative‑style side effects that alter global state.

Why Manage Side Effects?

Managing side effects in Jetpack Compose is essential for three reasons:

It aligns with the declarative programming model, where UI is repeatedly recomposed based on state.

Proper handling prevents unnecessary recompositions, improving performance and resource usage.

Correct lifecycle management avoids memory leaks, for example when registering listeners or launching network requests.

Jetpack Compose Side‑Effect APIs

LaunchedEffect

Definition: Starts a coroutine tied to the composable’s lifecycle. The coroutine restarts whenever the specified key changes.

Typical Use‑Cases: Performing asynchronous work such as network calls when a piece of state changes.

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.delay
import androidx.compose.material.Button

@Composable
fun LaunchedEffectDemo() {
    var count by remember { mutableStateOf(0) }
    var result by remember { mutableStateOf(0) }

    // Executes on first composition and whenever 'count' changes
    LaunchedEffect(count) {
        println("Count changed")
        delay(1000) // Simulate network request
        result++
    }

    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier.padding(top = 80.dp)
    ) {
        Text(text = "Count: $count  result=$result")
        Button(onClick = { count++ }) { Text("Add") }
    }
}

Key Points:

Ideal for side effects directly linked to state changes.

When the key changes, the previous coroutine is cancelled and a new one starts.

rememberCoroutineScope

Definition: Returns a CoroutineScope that can launch coroutines from a composable, typically in response to user interactions.

Typical Use‑Cases: Launching asynchronous work such as network requests or file I/O without tying the coroutine to a specific state key.

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.material.Button
import androidx.compose.runtime.rememberCoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

@Composable
fun CoroutineScopeDemo() {
    val coroutineScope = rememberCoroutineScope()
    var count by remember { mutableStateOf(0) }
    var result by remember { mutableStateOf(0) }

    Column(
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = Modifier.padding(top = 80.dp)
    ) {
        Text(text = "Count: $count  result=$result")
        Button(onClick = {
            coroutineScope.launch {
                delay(1000) // Simulate delay
                result++ // Update state after async work
            }
        }) { Text("Click") }
    }
}

Key Points: Provides a convenient way to start coroutines from UI events while keeping them scoped to the composable’s lifecycle.

SideEffect

Definition: Executes a block of code after every successful recomposition.

Typical Use‑Cases: Logging, debugging, or updating external systems that do not affect composable state.

import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.Alignment
import androidx.compose.material.Button

@Composable
fun SideEffectDemo() {
    var count by remember { mutableStateOf(0) }

    SideEffect {
        // Runs on every recomposition
        println("Current count: $count")
    }

    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Text(text = "Count: $count")
        Button(onClick = { count++ }) { Text("Click") }
    }
}

Key Points:

Runs after each recomposition, independent of any specific state key.

Useful for actions that should happen whenever the UI refreshes.

DisposableEffect

Definition: Executes cleanup code when the composable leaves the composition, typically used to unregister listeners or release resources.

Typical Use‑Cases: Canceling network requests, unregistering sensor listeners, or any other resource that needs explicit disposal.

import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext

@Composable
fun DisposableEffectDemo() {
    val context = LocalContext.current
    var sensorData by remember { mutableStateOf("No data") }

    DisposableEffect(Unit) {
        val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
        val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)

        val listener = object : SensorEventListener {
            override fun onSensorChanged(event: SensorEvent) {
                sensorData = "X: ${event.values[0]}, Y: ${event.values[1]}, Z: ${event.values[2]}"
            }
            override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
        }

        sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_NORMAL)

        onDispose {
            sensorManager.unregisterListener(listener)
        }
    }

    Text(text = sensorData, modifier = Modifier.fillMaxSize())
}

Key Points: Using onDispose guarantees that resources are released when the composable is removed, preventing memory leaks.

Conclusion

Understanding and correctly applying Jetpack Compose’s side‑effect APIs— LaunchedEffect, rememberCoroutineScope, SideEffect, and DisposableEffect —significantly improves app performance, resource management, and maintainability. Proper side‑effect handling ensures smoother state transitions, avoids unnecessary recompositions, and leads to a better overall user experience in modern declarative UI development.

Android UIJetpack ComposeSide EffectsDisposableEffectLaunchedEffectrememberCoroutineScope
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.