Android连续登录计数器数据检索异常:日期与Streak数据获取失败
问题分析与修复方案
核心问题
- ViewModel数据检索函数逻辑错误:
streakDataHandler作为挂起函数,却自行创建协程异步收集Flow,导致函数直接返回初始值null,此时Flow还未完成数据收集。 - 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
相关产品推荐
相关产品推荐

