we've encountered a problem with Jetpack Compose button actions leaking. We provide a class with resources (e.g strings, colors, and BUTTON ACTIONS):
data class CameraOnBoardingComposeViewResources(val title: String, val buttonTitle: String, val buttonAction: () -> Unit)
This data class is created in the fragment like so:
val resources = CameraOnBoardingComposeViewResources(
"Title", "ButtonTitle"
) { navigate() }
And in our composable we use those resources like so:
@Composable
fun composeOnBoardingView(resources: CameraOnBoardingComposeViewResources) {
Surface(
shape = RoundedCornerShape(4.dp),
color = colorResource(R.color.idenfyMainColorV2),
modifier = Modifier
.height(42.dp)
.padding(start = 16.dp, end = 16.dp)
.clickable(onClick = resources.buttonAction)
.fillMaxWidth()
)
}
The problem is that buttonAction leaks. How can we avoid this leak, should we somehow dispose of it, or do we need to change this architecture a bit?
EDIT After CommonsWare
Ok, I’ve located the problem, and it is indeed inside the composeOnBoardingView composable. It’s this code snippet:
val currentInstructionDescription: MutableState<String> = remember {
mutableStateOf("")
}
val progress = remember { mutableStateOf(0.0f) }
val handler = Handler(Looper.getMainLooper())
exoPlayer?.apply {
val runnable = object : Runnable {
override fun run() {
progress.value =
exoPlayer.currentPosition.toFloat() / exoPlayer.duration.toFloat()
currentInstructionDescription.value = InstructionsDescriptionBuilder.build(
context,
(resources.documentCenterImageUiViewModel as OnBoardingCenterImageUIViewModel.DocumentResource).step,
exoPlayer.currentPosition.toInt() / 1000
)
handler.postDelayed(this, 1000)
}
}
handler.post(runnable)
}
I tried disposing the handler like this:
val lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(lifecycleOwner) {
onDispose {
handler.removeCallbacksAndMessages(null)
}
}
But that did not solve the problem. Any ideas?
EDIT The issue is solved thanks CommonsWare! We switched to the LaunchedEffect and coroutines for an every-second in-composition timer, rather than Handler