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

Android连续登录计数器数据检索异常:日期与Streak数据获取失败

问题分析与修复方案

核心问题

  1. ViewModel数据检索函数逻辑错误:streakDataHandler作为挂起函数,却自行创建协程异步收集Flow,导致函数直接返回初始值null,此时Flow还未完成数据收集。
  2. Composable数据存储方式错误:使用普通var存储异步获取的数据,无法触发Composable重组,即使后续获取到数据,也无法被后续逻辑感知。

修复步骤

1. 修正ViewModel中的数据检索函数

移除自行创建的CoroutineScope,直接挂起等待Flow返回第一个数据:

suspend fun streakDataHandler(givenType: String = "lastDate"): AppData? {
    return appDataRepository.getDataStream(givenType)
        .map { dataList ->
            dataList.firstOrNull()
        }
        .firstOrNull() // 挂起直到获取Flow的第一个值,无数据则返回null
}

2. 修正Composable中的数据处理逻辑

使用mutableStateOf存储异步数据,确保数据更新能被捕获;同时简化空值处理:

val currentRetrievedDate = Date()
val currentDate = SimpleDateFormat("dd-MM-yyyy").format(currentRetrievedDate)

var lastDateObject by remember { mutableStateOf<AppData?>(null) }
LaunchedEffect(Unit) {
    lastDateObject = streakCounterViewModel.streakDataHandler()
}
val lastDate = lastDateObject?.content ?: "00-00-0000"

var currentStreakObject by remember { mutableStateOf<AppData?>(null) }
LaunchedEffect(Unit) {
    currentStreakObject = streakCounterViewModel.streakDataHandler("currentStreak")
}
val currentStreak = currentStreakObject?.content ?: "0"

进阶优化方案(推荐)

如果需要持续监听数据库数据变化(比如登录更新后自动同步连续登录次数),可以在ViewModel中直接暴露Flow,Composable用collectAsState自动收集:

ViewModel新增方法

fun getLastDateStream(): Flow<AppData?> {
    return appDataRepository.getDataStream("lastDate")
        .map { it.firstOrNull() }
}

fun getCurrentStreakStream(): Flow<AppData?> {
    return appDataRepository.getDataStream("currentStreak")
        .map { it.firstOrNull() }
}

Composable中使用

val currentRetrievedDate = Date()
val currentDate = SimpleDateFormat("dd-MM-yyyy").format(currentRetrievedDate)

val lastDateObject by streakCounterViewModel.getLastDateStream().collectAsState(initial = null)
val lastDate = lastDateObject?.content ?: "00-00-0000"

val currentStreakObject by streakCounterViewModel.getCurrentStreakStream().collectAsState(initial = null)
val currentStreak = currentStreakObject?.content ?: "0"

这种方式无需手动管理协程,自动响应数据变化,更符合Jetpack Compose的架构设计。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 08:23:09