Side Effect: Disposable Effect - devrath/ComposeAlchemy GitHub Wiki
About Disposable Effect
- Disposable effect is a composable function that is executed when the composable function is first loaded/rendered and it gets disposed of when the composable is removed from the UI hierarchy.
- This is useful when some clean-up operations need to be done when the composable is not in the UI hierarchy.
- Example
listeners
andanimations
. - Use cases of this
- Adding and removing event listeners
- Starting and stopping animations
- Bind and unbinding sensor resources such as Camera, LocationManager, etc
- Managing database connections
Disposable Effect: Example-1
- Observing the lifecycle changes in the composable
@Composable
fun TypeDisposableEffectDemo2Screen(modifier: Modifier = Modifier) {
val lifecycleOwner = LocalLifecycleOwner.current
val lifecycle = lifecycleOwner.lifecycle
DisposableEffect(lifecycle) {
// Create the observer
val observer = LifecycleEventObserver { source , event ->
when(event){
Lifecycle.Event.ON_CREATE -> println("ON_CREATE is invoked")
Lifecycle.Event.ON_START -> println("ON_START is invoked")
Lifecycle.Event.ON_RESUME -> println("ON_RESUME is invoked")
Lifecycle.Event.ON_PAUSE -> println("ON_PAUSE is invoked")
Lifecycle.Event.ON_STOP -> println("ON_STOP is invoked")
Lifecycle.Event.ON_DESTROY -> println("ON_DESTROY is invoked")
Lifecycle.Event.ON_ANY -> println("ON_ANY is invoked")
}
}
// Add the observer to lifecycle
lifecycle.addObserver(observer)
onDispose {
// Remove the observer from lifecycle
lifecycle.removeObserver(observer)
}
}
}
Disposable Effect: Example-2
- Launching a Job and canceling in a composable
Output
<!------------------ When the screen is first loaded ------------------------!>
Root composable composition occurs
Column composable composition occurs
DisposableEffect scope is invoked
Timer is still working 1
Timer is still working 2
Timer is still working 3
Timer is still working 4
<!----- When we press the back button so composable is destroyed ------------!>
Dispose invoked
Observation
- Note all the composables are composed only then the
DisposableEffect
scope is entered - When we press the back button composables are destroyed, note now the
Dispose
is triggered from theDisposableEffect
Code
@Composable
fun TypeDisposableEffect(navController: NavHostController) {
val timeTaken = remember{ mutableIntStateOf(0) }
println("Root composable composition occurs")
Column(
modifier = Modifier
.fillMaxSize()
.padding(10.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
println("Column composable composition occurs")
DisposableEffect(Unit) {
println("DisposableEffect scope is invoked")
val scope = CoroutineScope(Dispatchers.Default)
val job = scope.launch {
while (timeTaken.value<4) {
delay(1000)
timeTaken.value += 1
println("Timer is still working ${timeTaken.value}")
}
}
onDispose {
job.cancel()
println("Dispose invoked")
}
}
}
}