我正在研究连续计数功能,连续计数逻辑工作正常,但上次登录日期和上次连续记录的数据未正确获取。可能的原因是什么?
viewModel中用于数据检索的函数是:
suspend fun streakDataHandler(givenType: String = "lastDate"): AppData? {
val lastDateData: Flow<AppData?> = appDataRepository.getDataStream(givenType)
.map { dataList ->
dataList.firstOrNull()
}
val coroutineScope = CoroutineScope(Dispatchers.Main)
var data: AppData? = null
coroutineScope.launch {
lastDateData.collect { appData ->
if (appData != null) {
data = appData
}
else {
data = null
}
}
}
return data
}
检索和使用可组合文件中的数据的代码是:
val currentRetrievedDate: Date = Date()
val currentDate: String = SimpleDateFormat("dd-MM-yyyy").format(currentRetrievedDate)
var lastDateObject: AppData? = null
LaunchedEffect(Unit) {
lastDateObject = streakCounterViewModel.streakDataHandler()
}
var lastDate: String = "00-00-0000"
if (lastDateObject != null) {
lastDate = lastDateObject!!.content
}
var currentStreakObject: AppData? = null
LaunchedEffect(Unit) {
currentStreakObject = streakCounterViewModel.streakDataHandler("currentStreak")
}
var currentStreak: String = "0"
if (currentStreakObject != null) {
currentStreak = currentStreakObject!!.content
}
注意:此可组合文件不用于显示条纹,它只是计算它(并在本地数据库中更新它)并将牛排的值返回到另一个显示它的可组合文件。 我单独测试过,条纹计算逻辑存在问题。问题很可能只存在于数据检索中。
数据库有3列,第一列是自动生成的int id,第二列是字符串类型,第三列是内容,也是字符串并存储我想要检索的实际数据
完整项目位于 github 上:https://github.com/tauqirnizami/HealthEase
您遇到的问题是糟糕的架构和使用多种反模式的结果。当你清理它时,你的问题就会消失。
您的代码中有几个问题。以下内容与您当前的问题相关,因为它们表明架构不好:
viewModelScope
。StateFlow
。streakDataHandler
可能总是返回 null,因为启动的协程在返回之前无法足够快地更新 data
。以下问题可能与您当前的问题无关,但仍然应该修复:
这真的是你想要的吗:
if (appData != null) {
data = appData
} else {
data = null
}
与
data = appData
相同。
不要使用
!!
,它会使您的应用程序崩溃。用这个代替:
val lastDate: String = lastDateObject?.content ?: "00-00-0000"
// ...
val currentStreak: String = currentStreakObject?.content ?: "0"
修复架构问题需要进行一些重构。由于无法为您提供完美的解决方案,我只会展示这通常看起来如何:
private val givenType = MutableStateFlow("lastDate")
val appData: StateFlow<AppData?> = givenType
.flatMapLatest(appDataRepository::getDataStream)
.map(List<AppData>::firstOrNull)
.map {
// Call your use case to perform necessary calculations.
// This could even perform database updates.
}
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = null,
)
fun updateGivenType(givenType: String) {
this.givenType.value = givenType
}
现在,在您的可组合项中,您可以收集 appData 流。使用这个代替 LaunchedEffect:
val lastDateObject: AppData? by streakCounterViewModel.appData.collectAsStateWithLifecycle()
您应该调整此处所示的原则,以便在重构时使用它们。