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

从PHP API获取数据填充Flutter Table并修复length调用在null上的错误

问题修复方案

报错原因

你遇到的NoSuchMethodError: The getter 'length' was called on null报错由以下几个问题共同导致:

  • fetch方法返回值类型混乱:同时返回List<Model>和Table组件,类型不匹配
  • 数据解析逻辑错误:json解析后未调用Model.fromJson做实体转换,直接赋值给List<Model>类型变量导致数据为空
  • 未定义变量直接调用:代码中使用的toList变量未初始化,本身为null,调用map方法时内部会访问length属性触发报错
  • 字段不匹配:原有TableCell中使用的sn/name/address/phone等字段在你的Model实体类中不存在

修复实现

第一步:修正数据请求方法

请求方法只负责数据获取和解析,不处理UI渲染:

// 只负责请求数据,返回List<Model>
Future<List<Model>> fetchData() async {
  String apiurl = "替换为你的PHP接口实际地址";
  var response = await http.post(Uri.parse(apiurl), body: {
    'username': email // 传入实际的email参数
  });
  if(response.statusCode == 200) {
    // 如果API返回的是多个Model组成的数组,用下面的写法
    List jsonList = jsonDecode(response.body);
    return jsonList.map((item) => Model.fromJson(item)).toList();
    // 如果API返回的是单个Model对象(和你给出的示例结构一致),改成下面的写法:
    // return [Model.fromJson(jsonDecode(response.body))];
  } else {
    return [];
  }
}

第二步:用FutureBuilder异步渲染Table

在Widget的build方法中使用FutureBuilder加载异步数据,同时在每行末尾添加箭头标识:

@override
Widget build(BuildContext context) {
  return FutureBuilder<List<Model>>(
    future: fetchData(),
    builder: (context, snapshot) {
      // 加载中状态
      if (snapshot.connectionState == ConnectionState.waiting) {
        return const CircularProgressIndicator();
      }
      // 加载出错/无数据状态
      if (!snapshot.hasData || snapshot.data!.isEmpty) {
        return const Text("暂无数据");
      }
      List<Model> dataList = snapshot.data!;
      return Table(
        border: TableBorder.all(width:1, color:Colors.black45),
        children: [
          // 表头行,可根据实际需要展示的字段调整
          const TableRow(
            children: [
              TableCell(child: Padding(padding: EdgeInsets.all(5), child: Text("ID"))),
              TableCell(child: Padding(padding: EdgeInsets.all(5), child: Text("项目描述"))),
              TableCell(child: Padding(padding: EdgeInsets.all(5), child: Text("状态"))),
              TableCell(child: Padding(padding: EdgeInsets.all(5), child: Text("申请日期"))),
              TableCell(child: Padding(padding: EdgeInsets.all(5), child: Text("操作"))),
            ]
          ),
          // 遍历数据生成数据行
          ...dataList.map((model) {
            return TableRow(
              children: [
                TableCell(child: Padding(padding: const EdgeInsets.all(5), child: Text(model.id ?? ""))),
                TableCell(child: Padding(padding: const EdgeInsets.all(5), child: Text(model.bnDesc ?? ""))),
                TableCell(child: Padding(padding: const EdgeInsets.all(5), child: Text(model.reqStatus ?? ""))),
                TableCell(child: Padding(padding: const EdgeInsets.all(5), child: Text(model.reqDate?.toString().substring(0,10) ?? ""))),
                // 末尾列添加箭头标识
                TableCell(child: Padding(padding: const EdgeInsets.all(5), child: Icon(Icons.arrow_forward_ios, size: 16))),
              ]
            );
          }).toList()
        ],
      );
    }
  );
}

补充说明

可根据业务需要调整Table展示的字段,直接取model对应的属性即可;如果需要展示关联的tender列表数据,可在对应TableCell中嵌套多Widget实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 03:45:00