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

Jetpack Compose桌面国际象棋时钟Linux后台暂停问题求助

问题原因
  1. 调度器绑定问题:rememberCoroutineScope()默认使用Compose的UI线程调度器(Dispatchers.Main)。Linux桌面环境中,后台窗口的UI线程会被系统暂停非必要任务,导致协程里的delay(100)无法按时触发,时钟停止计数。Windows的后台调度策略不同,不会暂停这类任务,因此表现正常。
  2. 状态捕获问题:startClock函数的whiteTimeActive参数是协程启动时捕获的固定值,后续如果切换黑白方回合,协程无法感知值的变化,会导致时钟逻辑错误。
解决方案

1. 切换时钟协程到后台调度器

将时钟协程移至Dispatchers.Default(后台计算线程),确保后台运行时不受UI线程状态影响。同时更新Compose State时必须切回UI线程,因为State只能在UI线程修改。

修改后的startClock函数:

fun startClock(
    coroutineScope: CoroutineScope,
    whiteTimeActive: MutableState<Boolean>,
    onWhiteTimeDec: () -> Unit,
    onBlackTimeDec: () -> Unit
) : Job? {
    return coroutineScope.launch(Dispatchers.Default) {
        while (isActive) {
            delay(100)
            withContext(Dispatchers.Main) {
                if (whiteTimeActive.value) {
                    onWhiteTimeDec()
                } else {
                    onBlackTimeDec()
                }
            }
        }
    }
}

2. 调整UI逻辑支持动态切换回合

在预览组件中添加whiteTimeActive的State,并传递给时钟函数,同时添加切换按钮示例:

@Preview
@Composable
fun WorkingClockComponentPreview() {
    val allocatedTimeDeciSeconds = 15 * 10
    val coroutineScope = rememberCoroutineScope()
    var whiteTimeInDeciSeconds by remember { mutableStateOf(allocatedTimeDeciSeconds) }
    var blackTimeInDeciSeconds by remember { mutableStateOf(allocatedTimeDeciSeconds) }
    var clockActive by remember { mutableStateOf(false) }
    var clockJob by remember { mutableStateOf<Job?>(null) }
    var whiteTimeActive by remember { mutableStateOf(true) }

    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        SimpleClockComponent(
            whiteTimeInDeciSeconds = whiteTimeInDeciSeconds,
            blackTimeInDeciSeconds = blackTimeInDeciSeconds,
            whiteTimeActive = whiteTimeActive,
        )
        Button({
            whiteTimeInDeciSeconds = allocatedTimeDeciSeconds
            blackTimeInDeciSeconds = allocatedTimeDeciSeconds
            clockJob?.cancel()
            clockJob = startClock(coroutineScope, ::whiteTimeActive, {
                whiteTimeInDeciSeconds--
                if (whiteTimeInDeciSeconds <= 0) {
                    clockActive = false
                    clockJob?.cancel()
                }
            }, {
                blackTimeInDeciSeconds--
                if (blackTimeInDeciSeconds <= 0) {
                    clockActive = false
                    clockJob?.cancel()
                }
            })
        }) {
            Text("Start")
        }
        Button({
            whiteTimeActive = !whiteTimeActive
        }) {
            Text("Switch Player")
        }
    }
}

3. 补充缺失的时间格式化函数

确保代码可运行,添加getTimeText实现:

fun getTimeText(deciSeconds: Int): String {
    val totalSeconds = deciSeconds / 10
    val minutes = totalSeconds / 60
    val seconds = totalSeconds % 60
    val decimals = deciSeconds % 10
    return String.format("%02d:%02d.%d", minutes, seconds, decimals)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 17:44:55