Flutter/Dart:如何在同步函数中执行异步数据库操作?
问题分析
你的核心问题有两个:
addToLoadedMonths仅执行了数据库插入操作,但没有将当前月份添加到内存中的loadedMonths列表,导致每次切换月份时,isAlreadyLoaded都会判断为false,重复执行加载逻辑,引发懒加载异常。_onMonthChanged是同步函数,调用异步的addToLoadedMonths时未使用await,导致setState可能在数据库操作完成前执行,时序混乱进一步加剧了懒加载失效的问题。
修复步骤
1. 修改addToLoadedMonths函数
让它同时更新内存列表和数据库,并且返回Future以便外部等待执行完成:
Future<void> addToLoadedMonths(DateTime value) async { debugPrint("addToLoadedMonths called with value of: $value"); // 先更新内存列表,避免重复判断 if (!loadedMonths.any((date) => date.year == value.year && date.month == value.month)) { loadedMonths.add(value); } // 再执行数据库插入 await LoadedMonthsDatabase.instance.insertDateTime(value); }
2. 将_onMonthChanged改为异步函数
给函数加上async关键字,确保等待数据库操作完成后再更新UI:
Future<void> _onMonthChanged(DateTime? notRequired) async { DateTime value = DateTime(currentChosenDate.year, currentChosenDate.month); bool isAlreadyLoaded = loadedMonths.any((dateTime) => dateTime.year == value.year && dateTime.month == value.month); if (!isAlreadyLoaded) { for (int i = 0; i < recurringEvents.length; i++) { DateTime dateCounter = value; while (dateCounter.month == value.month) { int weekday = dateCounter.weekday; bool isRecurringDay = false; // 用Map简化星期判断逻辑,替代大量if-else final weekdayMap = { DateTime.sunday: everySunday!, DateTime.monday: everyMonday!, DateTime.tuesday: everyTuesday!, DateTime.wednesday: everyWednesday!, DateTime.thursday: everyThursday!, DateTime.friday: everyFriday!, DateTime.saturday: everySaturday!, }; isRecurringDay = weekdayMap[weekday] ?? false; if (isRecurringDay) { eventsList.add( NeatCleanCalendarEvent( recurringEvents[i].summary!, startTime: DateTime( dateCounter.year, dateCounter.month, dateCounter.day, chosenStartTime!.hour, chosenStartTime!.minute, ), endTime: DateTime( dateCounter.year, dateCounter.month, dateCounter.day, chosenEndTime!.hour, chosenEndTime!.minute, ), ), ); } dateCounter = dateCounter.add(const Duration(days: 1)); } } // 等待数据库操作完成后再更新UI await addToLoadedMonths(value); setState(() {}); } }
3. 补充初始化逻辑(必加)
应用启动时,需要从数据库读取已保存的月份到loadedMonths列表,避免重启后重复加载:
@override void initState() { super.initState(); _loadSavedLoadedMonths(); } Future<void> _loadSavedLoadedMonths() async { // 假设你的数据库有获取所有已保存DateTime的方法,比如getAllDateTime List<DateTime> savedMonths = await LoadedMonthsDatabase.instance.getAllDateTime(); setState(() { loadedMonths.addAll(savedMonths); }); }
关键提醒
- 异步函数必须通过
await等待执行完成,否则会导致代码时序混乱,UI更新不及时或逻辑错误。 - 内存列表
loadedMonths和数据库数据必须保持同步,否则会出现判断逻辑失效的问题。
内容的提问来源于stack exchange,提问作者Nandan Praveen
相关产品推荐
相关产品推荐

