LocalDate转"yyyy-MM-dd"应用崩溃,转"yyyy-MM-DD"日期值异常求助
问题解决步骤
1. 修正日期格式化模式错误
你当前使用的 yyyy-MM-DD 模式中,DD 代表一年中的第几天(范围001-366),这就是为什么2024年3月9日会被格式化为 2024-03-69(3月9日是2024年的第69天)。正确的月份中的第几天应该用小写的 dd,所以正确的格式是:
val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
2. 修复空指针崩溃问题
使用 !! 强制解包 localDate 会在 selectedDate.value 为 null 时触发空指针异常。主要原因有两个:
rememberSaveable默认无法序列化LocalDate,配置变更(如屏幕旋转)后selectedDate可能变为 null- 日历对话框可能在某些状态下返回 null 值
解决方案:
a. 为 LocalDate 添加 rememberSaveable 序列化器
创建一个自定义的 Saver 来保存 LocalDate:
object LocalDateSaver : Saver<LocalDate, String> { override fun restore(value: String): LocalDate = LocalDate.parse(value) override fun save(value: LocalDate): String = value.toString() }
然后修改 selectedDate 的初始化:
val selectedDate = rememberSaveable(stateSaver = LocalDateSaver) { mutableStateOf(LocalDate.now()) }
(去掉可空类型,因为初始值非空且序列化器能正确恢复)
b. 安全处理日期非空判断
替换强制解包 !! 为安全的 null 检查,并使用 LaunchedEffect 避免不必要的 ViewModel 调用:
val localDate = selectedDate.value val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") // 仅当日期变化时更新ViewModel中的日期 LaunchedEffect(localDate) { val formattedString = localDate.format(formatter) viewModel.saveDialogueDate(formattedString) }
3. 优化数据获取逻辑
当前 FetchTodayGamesData 中的 LaunchedEffect 使用 key1 = null,会导致仅在首次符合条件时执行,无法响应后续的日期变更。调整为使用 date 和 isClicked 作为触发键:
@Composable fun FetchTodayGamesData( mainViewModel: MainViewModel = hiltViewModel() ) { val date = mainViewModel.dialogueDate.observeAsState().value ?: LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) val isClicked = mainViewModel.isClicked.observeAsState().value ?: false LaunchedEffect(isClicked, date) { if (isClicked) { mainViewModel.getTodayMatches(date, 2023) mainViewModel.saveCalendarClicked(false) } } // ... 状态处理逻辑保持不变 }
这样每当 isClicked 变为 true 或 date 发生变化时,都会触发数据获取(仅当 isClicked 为 true 时执行)。
4. 额外优化建议
- 在 ViewModel 中直接使用
LocalDate而非字符串存储选中日期,避免重复格式化/解析的开销,仅在调用 API 时转换为字符串格式 - 确保日历对话框的
selection回调始终返回非空的LocalDate,进一步消除空值风险
内容的提问来源于stack exchange,提问作者Mahmoud Nabil
相关产品推荐
相关产品推荐

