Flutter解析邮轮JSON渲染列表时出现类型不匹配及空值报错问题
问题修复方案
问题1:类型不匹配错误 type 'CrusieModel' is not a subtype of type 'Map<String, dynamic>'
根源
你的API方法getPastCruise声明返回类型为Future<CrusieModel>,但状态码非200的分支中,你返回了Utilities.errorDialog的执行结果,该方法返回的是Widget类型,和声明的CrusieModel类型不匹配,触发类型转换异常。
修复方案
修改API类的错误分支逻辑,不要返回Widget,改为抛出异常,异常统一在UI层处理:
if(response.statusCode == 200){ return CrusieModel.fromJson(json.decode(response.body)); }else if(response.statusCode == 500){ throw Exception("There was an error getting the information from Atcore or Zoho"); }else{ throw Exception("Something went wrong"); }
问题2:空值检查运算符作用于空值错误
根源
你注释掉了FutureBuilder中snapshot.hasData的判断逻辑,Future处于pending加载状态时,snapshot.data本身为null,你直接使用!强制拆空就会触发该错误;同时模型类解析时没有做空值兼容,若接口返回PastCruises字段为null也会导致空异常。
修复方案
第一步:优化模型类空安全解析
修改CrusieModel.fromJson方法,兼容PastCruises为空的情况:
factory CrusieModel.fromJson(Map<String, dynamic> json) => CrusieModel( pastCruises: json["PastCruises"] == null ? [] : List<PastCruise>.from(json["PastCruises"].map((x) => PastCruise.fromJson(x))), );
同时修改PastCruise.fromJson中的日期解析逻辑,兼容日期字段为空的情况:
factory PastCruise.fromJson(Map<String, dynamic> json) => PastCruise( // 其他字段不变,仅修改日期相关的解析逻辑 departureDate: json["DepartureDate"] == null ? null : DateTime.parse(json["DepartureDate"]), returnDate: json["ReturnDate"] == null ? null : DateTime.parse(json["ReturnDate"]), modifiedDate: json["ModifiedDate"] == null ? null : DateTime.parse(json["ModifiedDate"]), // 其余字段保持不变 );
第二步:补全FutureBuilder的状态判断
修改ListView Widget中的FutureBuilder逻辑,覆盖加载、错误、空数据三种边界状态:
Widget listviewWidget(){ return FutureBuilder<CrusieModel>( future: pastCruises, builder: (context, snapshot){ // 加载中状态 if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } // 加载错误状态 if (snapshot.hasError) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text("加载失败:${snapshot.error}"), ElevatedButton( onPressed: () { // 这里加重新请求的逻辑 setState(() { pastCruises = getPastCruise(context, token); }); }, child: const Text("重试"), ) ], ), ); } // 空数据状态 if (!snapshot.hasData || snapshot.data?.pastCruises?.isEmpty == true) { return const Center(child: Text("暂无过往邮轮数据")); } // 有数据时渲染列表 final cruiseData = snapshot.data!; return ListView.builder( shrinkWrap: true, itemCount: cruiseData.pastCruises!.length, physics: const BouncingScrollPhysics(), itemBuilder: (context, index){ final pastCruise = cruiseData.pastCruises![index]; // 其余item渲染逻辑不变,直接用pastCruise对象取值即可 return Padding( padding: const EdgeInsets.symmetric(vertical: 8.0), child: Stack( children: [ // 原有的布局代码不变 ], ), ); } ); }, ); }
额外优化建议
- 检查接口返回的JSON字段大小写是否和模型类中解析的字段名完全一致,比如接口返回的是
pastCruises还是PastCruises,大小写不匹配会导致解析为null。 - 你同时在URL参数和请求头中传入了token,确认后端是否需要双传,避免冗余参数。
内容的提问来源于stack exchange,提问作者Vinay Bakle
相关产品推荐
相关产品推荐

