Atul Gupta
03/28/2025, 9:02 PMproduceState
and awaitDispose
with the code snippets in threadAtul Gupta
03/28/2025, 9:08 PM// this fun is just of logging composable getting added or removed from composition
@Composable
private inline fun LogAttachOrDetach(crossinline tag: () -> String) {
LaunchedEffect(Unit) {
Log.d("ProduceEffect", "${tag()}: Added in composition")
try
{
while (true)
{
delay(1000)
}
}
catch (e: CancellationException)
{
Log.d("ProduceEffect", "${tag()}: Removed from composition")
throw e
}
}
}
@Composable
private fun ProduceEffectParent() {
var shouldAnimate by remember {
mutableStateOf(true)
}
ProduceEffectChild(shouldAnimate) { shouldAnimate = it }
}
@Composable
private fun ProduceEffectChild(shouldAnimate: Boolean, onStateChange: (Boolean) -> Unit) {
if (shouldAnimate) {
LogAttachOrDetach { "ProduceEffectChild when true" }
produceState(0) {
value = 1
// animation handled
Log.d("ProduceEffect", "inside produce state before setting value to false")
onStateChange(false)
Log.d("ProduceEffect", "inside produce state after setting value to false and before delay")
// this will now avoid the call to awaitDispose
delay(100)
Log.d("ProduceEffect", "inside produce state after setting value to false and after delay if possible")
awaitDispose { Log.d("ProduceEffect", "disposed called for produce state") }
}
} else {
LogAttachOrDetach{ "ProduceEffectChild when false" }
}
}
now when delay(100)
is present awaitDispos
doesn't get called most of time with the following logs
ProduceEffectChild when true: Added in composition
inside produce state before setting value to false
inside produce state after setting value to false and before delay
ProduceEffectChild when true: Removed from composition
ProduceEffectChild when false: Added in composition
but when delay(100)
is comment then awaitDispose
gets called correctly like below
ProduceEffectChild when true: Added in composition
inside produce state before setting value to false
inside produce state after setting value to false and before delay
inside produce state after setting value to false and after delay if possible
disposed called for produce state
ProduceEffectChild when true: Removed from composition
ProduceEffectChild when false: Added in composition
I think in case when I explicitly call onStateChange
with false
to remove the produce state from composition, then it's scope gets cancelled any delay(100)
gets stuck. But even in that case should awaitDispose
gets called?
Also with delay(100)
this behaviour where awaitDispose
doesn't get called is not consistent