Flutter使用TableCalendar加载Firebase事件提示Event不是List<dynamic>子类型怎么解决
报错根因
table_calendar的eventLoader要求每个日期对应的事件必须是列表类型,但你当前的map存储的是单个Event对象,并非列表,当组件读取对应日期的事件时,拿到的单个Event和预期的List类型不匹配,就抛出了该错误,日期标红也是类型报错导致的渲染异常。
修复步骤
1. 调整存储事件的Map类型定义
把模型文件中的Map定义修改为明确的日期对应事件列表格式:
// 把原来的Map<DateTime, dynamic> map = {}; 替换为: Map<DateTime, List<Event>> map = {};
2. 修改事件存入Map的逻辑
存入事件时先判断当前日期对应的列表是否存在,不存在先初始化,再把Event加入列表,同时要把日期的时分秒清零,避免和isSameDay的判断逻辑不匹配,拉取完数据后调用setState刷新页面:
getEvents() async { var data = await FirebaseFirestore.instance.collection('events').get(); // 每次拉取前清空旧数据,避免重复累加 map.clear(); for (int i = 0; i < data.docs.length; i++) { var time = (data.docs[i]['date'] as Timestamp).toDate(); // 归一化日期,清除时分秒 var normalizedTime = DateTime(time.year, time.month, time.day); var event = Event(data.docs[i]['title']); // 不存在对应日期的列表则先初始化 if (map[normalizedTime] == null) { map[normalizedTime] = []; } map[normalizedTime]!.add(event); } // 刷新页面触发日历重绘 setState(() {}); }
3. 调整_getEventsForDay方法的返回类型
List<Event> _getEventsForDay(DateTime day) { final events = LinkedHashMap<DateTime, List<Event>>(equals: isSameDay, hashCode: getHashCode) ..addAll(map); return events[day] ?? []; }
4. (可选)自定义事件标记隐藏标题
如果不需要展示事件标题,只需要展示标记点,可以通过calendarBuilders自定义标记样式:
TableCalendar( firstDay: kFirstDay, lastDay: kLastDay, focusedDay: _focusedDay, eventLoader: _getEventsForDay, // 自定义事件标记,只展示小圆点 calendarBuilders: CalendarBuilders( markerBuilder: (context, date, events) { if (events.isEmpty) return const SizedBox(); return Container( margin: const EdgeInsets.only(top: 4), width: 6, height: 6, decoration: const BoxDecoration( color: Colors.blue, shape: BoxShape.circle, ), ); }, ), )
内容的提问来源于stack exchange,提问作者IBlackVikingl
相关产品推荐
相关产品推荐

