What is Side Effect?
Composable
functions are typically used to render UI elements. However, there are cases where composable functions need to execute code that is not related to the UI like sending analytics events or navigating to another screen given a certain state condition.
For those scenarios, you don't want to put those codes inside a Compose function due to the unpredictable composition.
Jetpack Compose Side Effect API
Jetpack Compose provides a number of APIs for handling side effects in your composable functions. These APIs allow you to encapsulate your side effects and make your code more readable and maintainable.
LaunchedEffect
LaunchedEffect
launches a coroutine to perform a long-running operation, such as a network request. The coroutine will be canceled when the composable is no longer used.
LaunchedEffect
takes two parameters:
key
: A key that is used to identify theLaunchedEffect
. If the key changes, the existing coroutine will be canceled and a new coroutine will be launched.coroutineScope
: A coroutine scope in which the side effect will be executed.
@Composable
fun UserProfile(userId: String) {
val userDetailsState = rememberMutableState { UserDetails() }
LaunchedEffect(key = userId) {
val userDetails = fetchUserDetails(userId)
userDetailsState.value = userDetails
}
// Display the user's name
Text(userDetailsState.value.name)
}
In this example, the LaunchedEffect will be launched when the composable function is first displayed. The LaunchedEffect will fetch the user's name from the network and store it in the userDetailsState variable. Once the user's name has been fetched, the composable function will be recomposed with the updated userDetailsState variable. This will cause the user's name to be displayed on the screen.
LaunchedEffect
is a powerful tool for performing side effects in Jetpack Compose. It allows you to perform asynchronous operations without blocking the composable function. This makes it a good choice for performing tasks such as fetching data from the network, playing sounds, and starting timers.
DisposableEffect
DisposableEffect
registers a callback to be invoked when the composable is no longer used. This can be used to clean up any resources that were allocated by the composable.
DisposableEffect
takes two parameters:
key: A key that is used to identify the
DisposableEffect
. If the key changes, the existingDisposableEffect
will be disposed of and a newDisposableEffect
will be created.effect: A block of code that performs the side effect. The onDispose block will be called when the composable leaves the Composition to clean up any resources that were used by the side effect.
@Composable
fun MyComposable() {
val button = Button(onClick = { })
DisposableEffect(key = button) {
val eventListener = object : OnClickListener {
override fun onClick(v: View) {
// Do something when the button is clicked
}
}
button.setOnClickListener(eventListener)
onDispose {
button.setOnClickListener(null)
}
}
// Display the button
button
}
In this example, the DisposableEffect
will register the event listener with the button when the composable function is first displayed. The DisposableEffect
will also unregister the event listener when the composable function leaves the Composition to prevent memory leaks.
DisposableEffect
can also be used to clean up other types of resources, such as animations and database connections. It is a powerful tool for managing resources in Jetpack Compose.
SideEffect
SideEffect
performs a side effect, such as logging or sending a notification. Side effects are not cleaned up when the composable is no longer used.
SideEffect
takes a single parameter:
- effect: A block of code that performs the side effect.
@Composable
fun MyComposable() {
val counter = remember { mutableStateOf(0) }
SideEffect {
counter.value += 1
}
// Display the counter value
Text("Counter: ${counter.value}")
}
In this example, the SideEffect
will update the counter variable whenever the composable function is recomposed. This will cause the composable function to be recomposed again, which will display the updated counter value on the screen.
Note for SideEffect
It is important to be careful when using SideEffect, as it can lead to performance problems if it is used incorrectly. For example, if you use SideEffect to update a shared variable that is used by multiple composable functions, this can lead to a cascading effect where all of the composable functions are recomposed unnecessarily.
It is generally best to use SideEffect sparingly and only for side effects that are absolutely necessary. If you need to perform a side effect that is more complex or asynchronous, you should consider using LaunchedEffect instead.