如何解决Jetpack Compose Button onClick事件内存泄漏问题?
Jetpack Compose按钮点击动作内存泄漏问题排查与解决
问题背景
最初遇到Jetpack Compose按钮点击动作泄漏的问题,首先定义了承载字符串、颜色、按钮点击动作等资源的类:
data class CameraOnBoardingComposeViewResources(val title: String, val buttonTitle: String, val buttonAction: () -> Unit)
该数据类在Fragment中创建方式如下:
val resources = CameraOnBoardingComposeViewResources( "Title", "ButtonTitle" ) { navigate() }
随后在Composable函数中按如下方式使用这些资源:
@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() ) }
最初怀疑是buttonAction导致内存泄漏,询问需要主动释放还是调整现有架构。
问题实际定位
收到CommonsWare回复后进一步排查,定位到问题实际出自composeOnBoardingView组合函数内部的定时任务代码:
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) }
尝试的无效修复方案
最初尝试通过DisposableEffect在组合销毁时释放handler回调,但问题没有解决:
val lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current DisposableEffect(lifecycleOwner) { onDispose { handler.removeCallbacksAndMessages(null) } }
最终解决方案
弃用Handler,改用Jetpack Compose原生的LaunchedEffect结合协程实现组合内的每秒定时任务,泄漏问题彻底解决。
内容的提问来源于stack exchange,提问作者Viktor Vostrikov
相关产品推荐
相关产品推荐

