Flutter如何将卡片轮播的硬编码数据替换为API返回的动态数据
报错根因
json.decode返回的列表默认是List<dynamic>类型,和你定义的List<Map<String, String>>类型不匹配,无法直接赋值,因此触发类型错误。
解决方案
- 第一步:把原来硬编码的
foodCategories改为状态层的可修改变量,注意和轮播组件引用的变量名保持一致(你当前轮播代码里用的是foodOptions,这里以统一改为foodCategories为例)
// 在页面的State类中定义状态变量 List<Map<String, String>> foodCategories = [];
- 第二步:修改API请求方法中的类型转换逻辑,手动把动态类型的列表转换为目标类型,拿到数据后调用
setState刷新UI
SharedPreferences? _prefs; void getCategories() async { try { _prefs = await SharedPreferences.getInstance(); var _categoryService = CategoryService(); var result = await _categoryService.getCategories(_prefs?.getString('token')); var categories = json.decode(result.body); // 核心类型转换逻辑 List<Map<String, String>> tempList = (categories as List).map((item) { return Map<String, String>.from(item as Map); }).toList(); // 赋值给状态变量并刷新UI setState(() { foodCategories = tempList; }); } catch (e) { print('分类请求失败:$e'); } }
- 第三步:修改轮播组件的数据源引用,若API返回的
image字段是网络URL,需要把AssetImage替换为NetworkImage
Container( height: 105, margin: const EdgeInsets.only( top: 20.0, bottom: 25.0, ), child: ListView.builder( scrollDirection: Axis.horizontal, padding: const EdgeInsets.only( left: 20.0, ), // 改为状态变量的长度 itemCount: foodCategories.length, itemBuilder: (context, index) { Map<String, String> option = foodCategories[index]; return Container( margin: const EdgeInsets.only(right: 35.0), child: Column( children: <Widget>[ Container( width: 70, height: 70, margin: const EdgeInsets.only(bottom: 10.0), decoration: BoxDecoration( borderRadius: BorderRadius.all( Radius.circular(5.0), ), image: DecorationImage( // 本地路径保留AssetImage,网络地址替换为NetworkImage image: NetworkImage(option['image']!), fit: BoxFit.cover, ), boxShadow: [ BoxShadow( blurRadius: 10.0, color: Colors.grey[300], offset: Offset(6.0, 6.0), ) ], ), ), Text( option['name'], style: TextStyle(fontSize: 17.0), ), ], ), ); }), ),
额外注意
- 页面初始化时需要在
initState生命周期中调用getCategories方法触发请求 - 可以增加加载状态判断,请求完成前显示占位组件,避免空列表阶段页面空白
内容的提问来源于stack exchange,提问作者jonah rimsy
相关产品推荐
相关产品推荐

