
本文档将指导你如何从 PHP API 获取数据,并使用 Flutter 的 `Table` 组件将其动态地展示出来。我们将重点解决 `NoSuchMethodError: The getter ‘length’ was called on null` 错误,并提供清晰的代码示例和注意事项,确保数据正确加载和显示。
从 PHP API 获取数据
首先,确保你已经创建了一个 Flutter 项目,并且已经添加了 http 依赖。你可以在 pubspec.yaml 文件中添加:
dependencies: http: ^0.13.0 # 请使用最新版本
然后,运行 flutter pub get 来安装依赖。
接下来,创建一个 Model 类来映射 API 返回的数据。根据你提供的 JSON 示例,已经定义了 Model 和 Tender 类。这里再贴一下,方便查阅:
立即学习“PHP免费学习笔记(深入)”;
class Model { Model({ this.id, this.goodsRef, this.loyer, this.bnCode, this.loyeeNo, this.contactName, this.contactTel, this.bnDesc, this.reqStatus, this.eMail, this.comments, this.tender, this.reqDate, this.sscOffice, }); final String id; final int goodsRef; final String loyer; final String bnCode; final int loyeeNo; final dynamic contactName; final dynamic contactTel; final String bnDesc; final String reqStatus; final dynamic eMail; final String comments; final List tender; final DateTime reqDate; final dynamic sscOffice; factory Model.fromJson(Map json) => Model( id: json["u0024id"] == null ? null : json["u0024id"], goodsRef: json["goods_ref"] == null ? null : json["goods_ref"], loyer: json["loyer"] == null ? null : json["loyer"], bnCode: json["bn_code"] == null ? null : json["bn_code"], loyeeNo: json["loyee_no"] == null ? null : json["loyee_no"], contactName: json["contact_name"], contactTel: json["contact_tel"], bnDesc: json["bn_desc"] == null ? null : json["bn_desc"], reqStatus: json["req_status"] == null ? null : json["req_status"], eMail: json["e_mail"], comments: json["comments"] == null ? null : json["comments"], tender: json["tender"] == null ? null : List.from(json["tender"].map((x) => Tender.fromJson(x))), reqDate: json["req_date"] == null ? null : DateTime.parse(json["req_date"]), sscOffice: json["ssc_office"], ); Map toJson() => { "u0024id": id == null ? null : id, "goods_ref": goodsRef == null ? null : goodsRef, "loyer": loyer == null ? null : loyer, "bn_code": bnCode == null ? null : bnCode, "loyee_no": loyeeNo == null ? null : loyeeNo, "contact_name": contactName, "contact_tel": contactTel, "bn_desc": bnDesc == null ? null : bnDesc, "req_status": reqStatus == null ? null : reqStatus, "e_mail": eMail, "comments": comments == null ? null : comments, "tender": tender == null ? null : List.from(tender.map((x) => x.toJson())), "req_date": reqDate == null ? null : reqDate.toIso8601String(), "ssc_office": sscOffice, };}class Tender { Tender({ this.id, this.goodsRef, this.inNo, this.tenderNo, this.closingDate, }); final String id; final int goodsRef; final int inNo; final String tenderNo; final String closingDate; factory Tender.fromJson(Map json) => Tender( id: json["u0024id"] == null ? null : json["u0024id"], goodsRef: json["goods_ref"] == null ? null : json["goods_ref"], inNo: json["in_no"] == null ? null : json["in_no"], tenderNo: json["tender_no"] == null ? null : json["tender_no"], closingDate: json["closing_date"] == null ? null : json["closing_date"], ); Map toJson() => { "u0024id": id == null ? null : id, "goods_ref": goodsRef == null ? null : goodsRef, "in_no": inNo == null ? null : inNo, "tender_no": tenderNo == null ? null : tenderNo, "closing_date": closingDate == null ? null : closingDate, };}
接下来,创建一个函数来从 API 获取数据:
import 'dart:convert';import 'package:http/http.dart' as http;import 'package:flutter/material.dart';Future<List> fetchItems(String email) async { String apiurl = "YOUR_API_URL"; // 替换为你的 API URL var response = await http.post(Uri.parse(apiurl), body: { 'username': email // 获取用户名 }); if (response.statusCode == 200) { // 使用 utf8.decode 处理中文乱码问题 final decodedBody = utf8.decode(response.bodyBytes); List jsonResponse = jsonDecode(decodedBody); List model = jsonResponse.map((item) => Model.fromJson(item)).toList(); return model; } else { throw Exception('Failed to load data from API'); }}
注意:
将 YOUR_API_URL 替换为你的 PHP API 的实际 URL。使用了 utf8.decode(response.bodyBytes) 来处理中文乱码问题,确保API返回的编码是UTF-8。
在 Flutter Table 中展示数据
现在,我们可以使用 FutureBuilder 来异步获取数据,并在 Table 组件中展示数据。
class MyTable extends StatefulWidget { @override _MyTableState createState() => _MyTableState();}class _MyTableState extends State { String email = "test@example.com"; // 替换为你的邮箱 Future<List> _dataFuture; @override void initState() { super.initState(); _dataFuture = fetchItems(email); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Data Table from API')), body: FutureBuilder<List>( future: _dataFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { return Center(child: Text('Error: ${snapshot.error}')); } else if (snapshot.hasData) { return buildTable(snapshot.data); } else { return Center(child: Text('No data available')); } }, ), ); } Widget buildTable(List data) { return SingleChildScrollView( // 确保表格在小屏幕上可以滚动 scrollDirection: Axis.horizontal, child: Table( border: TableBorder.all(width: 1, color: Colors.black45), columnWidths: { 0: FixedColumnWidth(100.0), // 可以自定义列宽 1: FixedColumnWidth(150.0), 2: FixedColumnWidth(200.0), 3: FixedColumnWidth(100.0), }, children: [ TableRow( // 表头 children: [ TableCell(child: Center(child: Padding(padding: EdgeInsets.all(5), child: Text('Goods Ref')))), TableCell(child: Center(child: Padding(padding: EdgeInsets.all(5), child: Text('BN Code')))), TableCell(child: Center(child: Padding(padding: EdgeInsets.all(5), child: Text('BN Desc')))), TableCell(child: Center(child: Padding(padding: EdgeInsets.all(5), child: Text('Req Status')))), ], ), ...data.map((item) { return TableRow( children: [ TableCell(child: Center(child: Padding(padding: EdgeInsets.all(5), child: Text(item.goodsRef?.toString() ?? '')))), TableCell(child: Center(child: Padding(padding: EdgeInsets.all(5), child: Text(item.bnCode ?? '')))), TableCell(child: Center(child: Padding(padding: EdgeInsets.all(5), child: Text(item.bnDesc ?? '')))), TableCell(child: Center(child: Padding(padding: EdgeInsets.all(5), child: Text(item.reqStatus ?? '')))), ], ); }).toList(), ], ), ); }}
关键点:
使用 FutureBuilder 来处理异步数据加载。在 buildTable 方法中,使用 data.map 来迭代数据并创建 TableRow。使用 item.propertyName ?? ” 来处理可能为 null 的值,避免 NoSuchMethodError 错误。 ?? 是 Dart 的 null-aware 运算符,如果 item.propertyName 为 null,则使用空字符串 ” 作为默认值。SingleChildScrollView 确保表格在小屏幕上可以滚动。添加了表头,使表格更易于理解。使用 columnWidths 来自定义列宽。
解决 NoSuchMethodError 错误
NoSuchMethodError: The getter ‘length’ was called on null 错误通常发生在尝试访问 null 值的属性时。在你的例子中,这很可能是因为 API 返回的数据中某些字段是 null,而你没有正确处理。
解决方法:
使用 null-aware 运算符 (??): 在访问可能为 null 的属性时,使用 ?? 运算符提供一个默认值。例如:Text(item.name ?? ”)。
检查 null 值: 在访问属性之前,可以使用 if (item.property != null) 来检查值是否为 null。
在 Model 类中处理 null 值: 在 Model 类的 fromJson 方法中,可以为可能为 null 的字段提供默认值。例如:
factory Model.fromJson(Map json) => Model( // ... bnDesc: json["bn_desc"] == null ? "" : json["bn_desc"], // ...);
总结
本文档介绍了如何从 PHP API 获取数据,并在 Flutter 的 Table 组件中展示数据。通过使用 FutureBuilder、null-aware 运算符和适当的错误处理,你可以创建一个动态的、数据驱动的表格。记住,处理 API 返回的 null 值是避免 NoSuchMethodError 错误的关键。希望本教程能够帮助你成功地构建你的 Flutter 应用!
以上就是从 PHP API 获取数据并在 Flutter Table 中展示的详细内容,更多请关注php中文网其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1324933.html
微信扫一扫
支付宝扫一扫