
本文档将指导你如何从 PHP API 获取数据,并使用 Flutter 的 `Table` 组件将其动态地展示出来。我们将重点解决 `NoSuchMethodError: The getter 'length' was called on null` 错误,并提供清晰的代码示例和注意事项,确保数据正确加载和显示。
首先,确保你已经创建了一个 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> tender;
final DateTime reqDate;
final dynamic sscOffice;
factory Model.fromJson(Map<String, dynamic> 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<Tender>.from(json["tender"].map((x) => Tender.fromJson(x))),
reqDate: json["req_date"] == null ? null : DateTime.parse(json["req_date"]),
sscOffice: json["ssc_office"],
);
Map<String, dynamic> 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<dynamic>.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<String, dynamic> 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<String, dynamic> 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<Model>> 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<dynamic> jsonResponse = jsonDecode(decodedBody);
List<Model> model = jsonResponse.map((item) => Model.fromJson(item)).toList();
return model;
} else {
throw Exception('Failed to load data from API');
}
}注意:
现在,我们可以使用 FutureBuilder 来异步获取数据,并在 Table 组件中展示数据。
class MyTable extends StatefulWidget {
@override
_MyTableState createState() => _MyTableState();
}
class _MyTableState extends State<MyTable> {
String email = "test@example.com"; // 替换为你的邮箱
Future<List<Model>> _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<Model>>(
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<Model> 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(),
],
),
);
}
}关键点:
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<String, dynamic> 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中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号