调用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
相关产品推荐
相关产品推荐

