You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose中Canvas组合项回调未触发问题排查

问题分析与解决方案

你的核心问题是:DetectionCanvas 中已经触发了 setErrorMode(能看到"TOO BIG"等日志),但上层传递的回调lambda里的日志未执行,showErrorMode 也没更新。结合代码和描述,大概率是回调作用域或状态捕获的问题,以下是具体排查和解决步骤:

1. 确认当前执行的分支

先明确代码走的是 foundDcode 分支还是 uiBoxes 分支,只有前者的回调包含更新逻辑。添加分支日志验证:

foundDcode?.let { dcode ->
    Log.d(UI_TEST, "当前走foundDcode分支")
    DetectionCanvas(listOf(dcode)) { newMode ->
        Log.d(UI_TEST, "SHOULD BE UPDATED TO $newMode")
        showErrorMode = newMode
    }
} ?: run {
    Log.d(UI_TEST, "当前走uiBoxes分支")
    DetectionCanvas(uiBoxes){}
}

如果日志显示走uiBoxes分支,说明foundDcode实际为null,需要检查viewModel.foundDcode的逻辑是否正确。

2. 稳定回调lambda的引用

Compose重组时会重新创建未被remember包裹的lambda,可能导致回调上下文丢失。用remember包裹回调,确保其引用稳定:

// 在CameraPreview中声明稳定的回调
val errorModeCallback = remember {
    { newMode: Int ->
        Log.d(UI_TEST, "SHOULD BE UPDATED TO $newMode")
        showErrorMode = newMode
    }
}

// 调用DetectionCanvas时传入稳定回调
foundDcode?.let { dcode ->
    DetectionCanvas(listOf(dcode), errorModeCallback)
} ?: DetectionCanvas(uiBoxes){}

3. 提升状态到ViewModel(推荐)

将showErrorMode从Compose局部状态移到ViewModel中,避免Compose作用域带来的状态丢失问题:

在ViewModel中添加状态:

private val _showErrorMode = MutableIntStateFlow(0)
val showErrorMode = _showErrorMode.asStateFlow()

fun updateErrorMode(mode: Int) {
    _showErrorMode.value = mode
}

在CameraPreview中使用:

// 替换原来的局部状态
val showErrorMode by viewModel.showErrorMode.collectAsState()

// 回调改为调用ViewModel方法
val errorModeCallback = remember {
    { newMode: Int ->
        Log.d(UI_TEST, "SHOULD BE UPDATED TO $newMode")
        viewModel.updateErrorMode(newMode)
    }
}

这种方式能确保状态不受Compose重组影响,且更符合MVVM架构规范。

4. 验证DetectionCanvas的核心逻辑

确认boxClosestToCenter的判断逻辑正确,添加日志检查:

@Composable
private fun DetectionCanvas(uiBoxes: List<UiBox>, setErrorMode: (Int) -> Unit ) {
    val boxClosestToCenter = uiBoxes.firstOrNull { it.isClosestToCenter }
    Log.d(UI_TEST, "找到的中心Box: $boxClosestToCenter")
    Log.d(UI_TEST, "所有UiBox的isClosestToCenter状态: ${uiBoxes.map { it.isClosestToCenter }}")
    
    // ... 其他原有代码
}

如果boxClosestToCenter为null,后续的尺寸判断和回调都不会执行,需要检查isClosestToCenter的赋值逻辑是否正确。

内容的提问来源于stack exchange,提问作者Michal Rymarski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 21:51:02