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

Flutter报错:_Map<String,dynamic>不是Iterable子类型问题求助

问题分析与解决方案

核心问题原因

报错type '_Map<String, dynamic>' is not a subtype of type 'Iterable'的本质是:接口返回的数据类型不稳定——首次进入时返回的是数组(List),再次进入时返回的是对象(Map,可能是接口返回的错误信息、状态码等非列表格式),而你直接用for-in遍历,默认把返回值当成了可迭代的列表,所以触发类型转换异常。

分步解决代码

1. 修复API请求的类型判断逻辑

先对接口返回数据做类型校验,区分列表和对象场景:

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter/foundation.dart';

Future<void> fetchBookingData(BuildContext context) async {
  final headers = {'Content-Type': 'application/json'}; // 示例请求头,根据实际调整
  final data = {'user_id': 'your_user_id'}; // 示例请求体,根据实际调整

  final response = await http.post(
    Uri.parse(AppUrl.getBooking),
    headers: headers,
    body: jsonEncode(data),
  );

  final responseData = jsonDecode(response.body);

  // 先判断返回数据类型,再处理
  if (responseData is List) {
    // 正常返回列表的场景,遍历数据并转成日历事件格式
    final calendarEvents = responseData.map((item) => CalendarEvent(
      date: DateTime.parse(item['booking_date']), // 替换为接口实际日期字段
      title: item['name'] ?? '无标题',
    )).toList();
    // 通知Provider更新事件数据
    Provider.of<CalendarEventProvider>(context, listen: false).updateEvents(calendarEvents);
  } else if (responseData is Map) {
    // 接口返回错误信息的场景,比如token过期、参数错误
    if (kDebugMode) {
      print('请求失败:${responseData['msg'] ?? '未知错误'}');
    }
    // 可清空现有事件或保留,也可弹出提示
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(responseData['msg'] ?? '获取预约数据失败')),
    );
  } else {
    if (kDebugMode) {
      print('接口返回格式异常');
    }
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('数据格式错误,请重试')),
    );
  }
}

2. 创建Provider管理日历事件状态

用Provider统一管理日历事件,确保页面能自动响应数据变化:

import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';

// 日历事件模型
class CalendarEvent {
  final DateTime date;
  final String title;

  CalendarEvent({required this.date, required this.title});
}

// Provider类
class CalendarEventProvider extends ChangeNotifier {
  List<CalendarEvent> _events = [];

  List<CalendarEvent> get events => _events;

  // 根据日期筛选对应事件,适配TableCalendar的eventLoader回调
  List<CalendarEvent> getEventsForDay(DateTime day) {
    return _events.where((event) => isSameDay(event.date, day)).toList();
  }

  // 更新事件列表
  void updateEvents(List<CalendarEvent> newEvents) {
    _events = newEvents;
    notifyListeners();
  }

  // 清空事件
  void clearEvents() {
    _events.clear();
    notifyListeners();
  }
}

3. 页面中结合TableCalendar使用Provider

在页面中通过Consumer监听Provider数据,渲染日历:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:table_calendar/table_calendar.dart';

class BookingCalendarPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('我的预约')),
      body: Consumer<CalendarEventProvider>(
        builder: (context, provider, child) {
          return TableCalendar(
            firstDay: DateTime.now().subtract(const Duration(days: 180)),
            lastDay: DateTime.now().add(const Duration(days: 180)),
            focusedDay: DateTime.now(),
            eventLoader: provider.getEventsForDay,
            // 自定义事件标记样式
            calendarBuilders: CalendarBuilders(
              markerBuilder: (context, date, events) {
                if (events.isNotEmpty) {
                  return Positioned(
                    bottom: 1,
                    right: 1,
                    child: Container(
                      width: 16,
                      height: 16,
                      decoration: const BoxDecoration(
                        color: Colors.blue,
                        shape: BoxShape.circle,
                      ),
                      child: Center(
                        child: Text(
                          '${events.length}',
                          style: const TextStyle(color: Colors.white, fontSize: 10),
                        ),
                      ),
                    ),
                  );
                }
                return null;
              },
            ),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => fetchBookingData(context),
        child: const Icon(Icons.refresh),
      ),
    );
  }
}

额外注意事项

  • 确保接口返回的日期格式是可被DateTime.parse解析的标准格式(如yyyy-MM-dd),如果格式不统一,要增加日期解析的异常捕获。
  • 可以把API请求逻辑封装到Provider的方法中,避免页面代码冗余。
  • 首次进入页面时,可在initState中调用fetchBookingData自动加载数据。

内容的提问来源于stack exchange,提问作者Deepak Sonkar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 16:25:24