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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 19:15:03