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

Flutter中SQLite数据无法映射到Reminder列表,APP无法显示求助

问题原因与解决方案

核心问题

你直接将Day/Activity枚举的toString()结果(格式如Day.monday)和TimeOfDay的toString()结果(格式如TimeOfDay(hour:8, minute:0))存入数据库,读取时却试图直接将字符串强制转换为对应类型,这会触发类型转换异常,无法生成有效的Reminder列表。

修复步骤

1. 修正数据存储格式

存储枚举时只保留枚举值名称(去掉前缀),存储TimeOfDay时使用标准化的时间字符串格式:

void addReminder(Day day, TimeOfDay time, Activity activity) async {
  final db = await _getDatabase();
  final newReminder = Reminder(day: day, targetTime: time, activity: activity);
  try {
    // 提取枚举值名称(如"monday"而非"Day.monday")
    final dayStr = day.toString().split('.').last;
    final activityStr = activity.toString().split('.').last;
    // 将TimeOfDay转为"HH:mm"格式字符串
    final timeStr = '${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}';
    
    await db.rawInsert(
        'INSERT INTO userReminders(day, targetTime, activity) VALUES(?, ?, ?)',
        [dayStr, timeStr, activityStr]
    );
    state = [newReminder, ...state];
  } catch (e) {
    print('Error inserting reminder: $e');
  }
}

2. 实现字符串到目标类型的转换函数

取消注释并完善转换逻辑:

// 字符串转Day枚举
Day dayFromString(String value) {
  return Day.values.firstWhere(
    (e) => e.toString().split('.').last == value,
    orElse: () => Day.monday, // 可选:设置默认值避免无匹配项报错
  );
}

// 字符串转Activity枚举
Activity activityFromString(String value) {
  return Activity.values.firstWhere(
    (e) => e.toString().split('.').last == value,
    orElse: () => Activity.wakeUp, // 可选:设置默认值
  );
}

// "HH:mm"格式字符串转TimeOfDay
TimeOfDay timeStringToTimeOfDay(String timeStr) {
  final parts = timeStr.split(':');
  return TimeOfDay(hour: int.parse(parts[0]), minute: int.parse(parts[1]));
}

3. 修正数据读取逻辑

在loadReminders中调用转换函数,将数据库字符串转为对应类型:

Future<void> loadReminders() async {
  final db = await _getDatabase();
  final data = await db.rawQuery('SELECT * FROM userReminders');

  print(data);
  final reminders = data.map((e) => Reminder(
    day: dayFromString(e['day'] as String),
    targetTime: timeStringToTimeOfDay(e['targetTime'] as String),
    activity: activityFromString(e['activity'] as String),
  )).toList();
  
  print(data.isEmpty);
  state = reminders;
}

4. 额外说明

  • 若数据库中已有旧格式数据,需清空数据库或编写迁移逻辑转换旧数据,否则读取旧数据时仍会报错。
  • 使用参数化查询(?占位符)替代字符串拼接,可避免SQL注入风险与字符串转义问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 04:32:19