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

调用HTTP API在Carousel Slider展示产品时遭遇类型错误求助

错误原因与修复方案

核心错误原因

你遇到的类型错误,是因为API返回的data是Map结构(格式为{"data": [产品数组]}),你直接对整个Map调用map()方法,但Map的map()方法要求回调函数必须接收(String, dynamic)类型的参数(键和值),并返回MapEntry,但你传入的是处理单个产品对象的函数,类型完全不匹配,因此抛出类型错误。

另外,你在Widget中通过data['data'][item]['name']访问属性的方式也是错误的,因为如果item是数组中的元素,直接用item['name']即可。


具体修复步骤

1. 修正API数据解析逻辑

在getData()方法中,直接提取出产品数组,将data变量转为List类型:

Future<void> getData() async {
  final response = await http.get(Uri.parse('https://berequirement.herokuapp.com/products'));

  if (response.statusCode == 200) {
    // 直接取出data字段对应的产品数组,而非整个Map
    data = jsonDecode(response.body)['data'];
  } else {
    // 新增错误处理,避免空数据导致后续崩溃
    setState(() {
      data = [];
    });
  }
}

2. 修正CarouselSlider的items遍历逻辑

现在data是产品数组,直接遍历数组,用item访问对应属性:

items: data.map((item) {
  return Builder(
    builder: (BuildContext context) {
      return Column(
        children: [
          Text(
            item['name'], // 直接用item访问属性
            style: GoogleFonts.poppins(
              fontWeight: FontWeight.bold,
              fontSize: 22,
            ),
          ),
          const SizedBox(height: 10),
          Text(
            "Item No . ${item['code']}",
            textAlign: TextAlign.center,
            style: GoogleFonts.poppins(
                fontSize: 12,
                color: Colors.grey),
          ),
          const SizedBox(height: 5),
          Text(
            "Item Type . ${item['type']}",
            textAlign: TextAlign.center,
            style: GoogleFonts.poppins(
                fontSize: 13,
                color: Colors.black),
          ),
          Text(
            "\$ ${item['price']}",
            style: GoogleFonts.poppins(
              textStyle: const TextStyle(
                  fontWeight: FontWeight.bold,
                  color: Colors.black,
                  fontSize: 22),
            ),
          ),
        ],
      );
    },
  );
}).toList(),

3. 避免FutureBuilder重复发起请求

每次build都会调用getData(),导致重复请求API,建议在initState中初始化请求:

@override
void initState() {
  super.initState();
  getData(); // 只在页面初始化时请求一次
}

更严谨的做法是存储Future对象,防止重复执行:

late Future<void> _fetchDataFuture;

@override
void initState() {
  super.initState();
  _fetchDataFuture = getData();
}

// 后续FutureBuilder的future改为_fetchDataFuture
FutureBuilder(
  future: _fetchDataFuture,
  // ...其他代码
)

4. 完善异常与空数据处理

在FutureBuilder中添加请求失败的UI提示:

if (snapshot.connectionState == ConnectionState.waiting) {
  return const Center(child: Text('Loading ...'));
} else if (data == null || data.isEmpty) {
  return const Center(child: Text('Failed to load products'));
} else {
  // 原有的CarouselSlider布局代码
}

完整修复后的代码片段

class HomePage extends Stateful Widget {
  final List<String> items;
  const HomePage({
    Key? key,
    required this.items,
  }) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int activeIndex = 0;
  var data;
  late Future<void> _fetchDataFuture;

  setActiveDot(index) {
    setState(() {
      activeIndex = index;
    });
  }

  Future<void> getData() async {
    final response = await http.get(Uri.parse('https://berequirement.herokuapp.com/products'));

    if (response.statusCode == 200) {
      data = jsonDecode(response.body)['data'];
    } else {
      setState(() {
        data = [];
      });
    }
  }

  @override
  void initState() {
    super.initState();
    _fetchDataFuture = getData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Expanded(
            child: FutureBuilder(
              future: _fetchDataFuture,
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.waiting) {
                  return const Center(child: Text('Loading ...'));
                } else if (data == null || data.isEmpty) {
                  return const Center(child: Text('Failed to load products'));
                } else {
                  return Stack(
                    children: <Widget>[
                      SizedBox(
                        height: 500,
                        width: 400,
                        child: CarouselSlider(
                          options: CarouselOptions(
                            autoPlayCurve: Curves.fastLinearToSlowEaseIn,
                            autoPlayAnimationDuration: const Duration(seconds: 1),
                            viewportFraction: 1.0,
                            onPageChanged: (index, reason) {
                              setActiveDot(index);
                            },
                          ),
                          items: data.map((item) {
                            return Builder(
                              builder: (BuildContext context) {
                                return Column(
                                  children: [
                                    Text(
                                      item['name'],
                                      style: GoogleFonts.poppins(
                                        fontWeight: FontWeight.bold,
                                        fontSize: 22,
                                      ),
                                    ),
                                    const SizedBox(height: 10),
                                    Text(
                                      "Item No . ${item['code']}",
                                      textAlign: TextAlign.center,
                                      style: GoogleFonts.poppins(
                                          fontSize: 12,
                                          color: Colors.grey),
                                    ),
                                    const SizedBox(height: 5),
                                    Text(
                                      "Item Type . ${item['type']}",
                                      textAlign: TextAlign.center,
                                      style: GoogleFonts.poppins(
                                          fontSize: 13,
                                          color: Colors.black),
                                    ),
                                    Text(
                                      "\$ ${item['price']}",
                                      style: GoogleFonts.poppins(
                                        textStyle: const TextStyle(
                                            fontWeight: FontWeight.bold,
                                            color: Colors.black,
                                            fontSize: 22),
                                      ),
                                    ),
                                  ],
                                );
                              },
                            );
                          }).toList(),
                        ),
                      ),
                      Positioned(
                        left: 0,
                        right: 0,
                        bottom: 10,
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.end,
                          children: List.generate(data.length, (idx) {
                            return activeIndex == idx
                                ? const ActiveDot()
                                : const InactiveDot();
                          }),
                        ),
                      )
                    ],
                  );
                }
              },
            ),
          ),
        ],
      ),
    );
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 16:25:21