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

从返回栈恢复后停车时长文本消失问题求助

解决方案:后台恢复后停车时长文本消失问题

核心问题分析

日志正常输出但UI不更新,说明状态duration确实在更新,但Compose重组未触发UI刷新,或者后台期间状态被意外重置但协程仍在运行。直接将组件移到父布局后内容消失,可能与remember的作用域或Compose的后台重组限制有关。

具体修复方案

1. 用rememberSaveable持久化状态

将duration的remember替换为rememberSaveable,确保App后台/进程回收后状态不丢失:

// 原代码
var duration by remember { mutableStateOf("") }
// 修改为
var duration by rememberSaveable { mutableStateOf("") }

2. 绑定LaunchedEffect到关键参数

将LaunchedEffect的key从Unit改为startingDate和startingTime,确保当停车起始时间变化时协程能重启,同时后台恢复后也能正确关联最新参数:

LaunchedEffect(startingDate, startingTime) {
    updateDuration() // 首次加载立即计算,避免初始空文本
    while (true) {
        delay(1000)
        updateDuration()
    }
}

3. 监听App生命周期,恢复时强制更新

添加生命周期监听,当App从后台回到前台时手动触发状态更新,确保UI同步:

val lifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(lifecycleOwner) {
    val observer = LifecycleEventObserver { _, event ->
        if (event == Lifecycle.Event.ON_RESUME) {
            updateDuration()
        }
    }
    lifecycleOwner.lifecycle.addObserver(observer)
    onDispose {
        lifecycleOwner.lifecycle.removeObserver(observer)
    }
}

4. 优化时长计算逻辑(可选)

避免每次解析日期字符串,在ViewModel层预处理并保存起始时间戳,减少重复解析开销:

// ViewModel中保存起始时间戳
val startTimestamp = mutableStateOf(System.currentTimeMillis())

// 时长计算简化为
val currentDuration = (System.currentTimeMillis() - startTimestamp.value) / 1000

完整修复后的时长组件代码

@Composable
fun ParkingDurationText(startingDate: String?, startingTime: String?) {
    val context = LocalContext.current
    val dateFormatter = DateTimeFormatter.ofPattern(ConstHelper.TimePatterns.DATE_PATTERN)
    val timeFormatter = DateTimeFormatter.ofPattern(ConstHelper.TimePatterns.TIME_PATTERN)
    val dateTimeFormatter = DateTimeFormatter.ofPattern(ConstHelper.TimePatterns.DATE_TIME_PATTERN)
    val lifecycleOwner = LocalLifecycleOwner.current

    // 用rememberSaveable持久化状态
    var duration by rememberSaveable { mutableStateOf("") }

    val updateDuration = {
        val startDateTime = LocalDateTime.parse(
            "${startingDate ?: LocalDate.now().format(dateFormatter)} ${startingTime ?: LocalTime.now().format(timeFormatter)}",
            dateTimeFormatter
        )
        val currentDuration = Duration.between(startDateTime, LocalDateTime.now()).seconds
        duration = "Days: ${currentDuration / 86400} Hours: ${(currentDuration % 86400) / 3600} Minutes: ${((currentDuration % 86400) % 3600) / 60} Seconds: ${currentDuration % 60}"
    }

    // 绑定LaunchedEffect到起始时间参数
    LaunchedEffect(startingDate, startingTime) {
        updateDuration()
        while (true) {
            delay(1000)
            updateDuration()
        }
    }

    // 监听ON_RESUME事件,后台恢复时强制更新
    DisposableEffect(lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            if (event == Lifecycle.Event.ON_RESUME) {
                updateDuration()
            }
        }
        lifecycleOwner.lifecycle.addObserver(observer)
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }

    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(5.dp),
        horizontalArrangement = Arrangement.Start,
        verticalAlignment = Alignment.CenterVertically
    ) {
        Text(
            modifier = Modifier.padding(end = 5.dp),
            text = stringResource(id = R.string.parking_duration),
            style = MaterialTheme.typography.bodyMedium,
            fontWeight = FontWeight.Bold
        )
        Text(
            text = duration,
            modifier = Modifier,
            style = MaterialTheme.typography.bodyMedium,
            textAlign = TextAlign.Center
        )
    }
}

额外建议

  • 避免在Composable中频繁执行日期解析操作,尽量在ViewModel层完成预处理
  • 测试时可开启开发者选项中的“不保留活动”,模拟后台进程回收场景验证状态恢复能力

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 02:57:36