flutter - Flutter:如何从 api 获取数据并绑定到 PaginatedDataTable
问题描述
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class DataTableDemo extends StatelessWidget {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Service History'),
),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
PaginatedDataTable(
header: Text('Service Details'),
rowsPerPage: 4,
columns: [
DataColumn(label: Text('SrNo.')),
DataColumn(label: Text('Customer Name')),
DataColumn(label: Text('Mobile Number')),
DataColumn(label: Text('Address')),
DataColumn(label: Text('Company')),
DataColumn(label: Text('Model')),
DataColumn(label: Text('REGNo')),
],
source: _DataSource(context),
),
],
),
);
}
}
fetchSummary() async {
final response = await http.get('https://api');
if (response.statusCode == 200) {
var parsed = json.decode(response.body);
List jsonResponse = parsed["Table"] as List;
return jsonResponse.map((job) => new _Row.fromJson(job)).toList();
} else {
print('Error, Could not load Data.');
throw Exception('Failed to load Data');
}
}
class _Row {
_Row(
this.srNo,
this.customerName,
this.mobileNumber,
this.address,
this.company,
this.model,
this.rEGNo,
);
final int srNo;
final String customerName;
final String mobileNumber;
final String address;
final String company;
final String model;
final String rEGNo;
bool selected = false;
factory _Row.fromJson(Map<String, dynamic> json) {
return _Row(
json['SrNo'],
json['CustomerName'],
json['MobileNumber'],
json['Address'],
json['Company'],
json['Model'],
json['REGNo'],
);
}
}
class _DataSource extends DataTableSource {
_DataSource(this.context) {
_rows =
fetchSummary();
}
final BuildContext context;
List<_Row> _rows;
int _selectedCount = 0;
@override
DataRow getRow(int index) {
assert(index >= 0);
if (index >= _rows.length) return null;
final row = _rows[index];
return DataRow.byIndex(
index: index,
//selected: row.selected,
onSelectChanged: (value) {
if (row.selected != value) {
_selectedCount += value ? 1 : -1;
assert(_selectedCount >= 0);
row.selected = value;
notifyListeners();
}
},
cells: [
DataCell(Text(row.srNo.toString())),
DataCell(Text(row.customerName)),
DataCell(Text(row.mobileNumber)),
DataCell(Text(row.address)),
DataCell(Text(row.company)),
DataCell(Text(row.model)),
DataCell(Text(row.rEGNo)),
],
);
}
@override
int get rowCount => _rows.length;
@override
bool get isRowCountApproximate => false;
@override
int get selectedRowCount => _selectedCount;
}
我试过这段代码,但绑定数据时出错。当我调用 API 并从服务器获取数据(Json 格式)时,无法转换数据并出现错误。如何转换我的数据并绑定到 PaginatedDataTable。
源代码来自:[https://material.io/components/data-tables/flutter#theming-data-tables]。
解决方案
您需要的是更改通知器。
让我们做一个简单的例子。
这是我的模型:
{
"id":1,
"name": "John Doe",
"username":"johndoe",
"email":"johndoe@mail.com",
"address":"address",
"phone":"1234567890",
"website":"johndoe.com",
"company":"johndoe pty ltd"
}
那么我的颤振数据模型将如下所示:
import 'dart:convert';
List<UserModel> userModelFromJson(String str) =>
List<UserModel>.from(json.decode(str).map((x) => UserModel.fromJson(x)));
String userModelToJson(List<UserModel> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class UserModel {
UserModel({
this.id,
this.name,
this.username,
this.email,
this.address,
this.phone,
this.website,
this.company,
});
int id;
String name;
String username;
String email;
Address address;
String phone;
String website;
Company company;
factory UserModel.fromJson(Map<String, dynamic> json) => UserModel(
id: json["id"],
name: json["name"],
username: json["username"],
email: json["email"],
address: Address.fromJson(json["address"]),
phone: json["phone"],
website: json["website"],
company: Company.fromJson(json["company"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"username": username,
"email": email,
"address": address.toJson(),
"phone": phone,
"website": website,
"company": company.toJson(),
};
}
接下来,我将为该类创建一个数据更改通知器UserModel
:
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart' show PaginatedDataTable;
class UserDataNotifier with ChangeNotifier {
UserDataNotifier() {
fetchData();
}
List<UserModel> get userModel => _userModel;
var _userModel = <UserModel>[]
Future<void> fetchData() async {
_userModel = await Api.fetchData();
notifyListeners();
}
}
请注意,我们使用_userModel = await Api.fetchData();
它可以是您自己的 API 实现。如果您需要这方面的帮助,请查看Dio for Flutter。在 ChangeNotifier 的初始化时获取数据。
接下来,我们将创建一个数据源来容纳所有数据:
import 'package:flutter/material.dart';
class UserDataTableSource extends DataTableSource {
UserDataTableSource({
@required List<UserModel> userData,
@required this.onRowSelect,
}) : _userData = userData,
assert(userData != null);
final List<UserModel> _userData;
final OnRowSelect onRowSelect;
@override
DataRow getRow(int index) {
assert(index >= 0);
if (index >= _userData.length) {
return null;
}
final _user = _userData[index];
return DataRow.byIndex(
index: index, // DON'T MISS THIS
cells: <DataCell>[
DataCell(Text('${_user.name}')),
DataCell(Text('${_user.username}')),
DataCell(Text('${_user.email}')),
DataCell(Text('${_user.address}')),
DataCell(Text('${_user.phone}')),
DataCell(Text('${_user.website}')),
DataCell(Text('${_user.company}')),
],
);
}
@override
bool get isRowCountApproximate => false;
@override
int get rowCount => _userData.length;
@override
int get selectedRowCount => 0;
}
最后,我们将在 Widget 中使用这个 Change Notifier 和 DataSource:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class DataTableScreen extends StatelessWidget {
const DataTableScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
//
return Stack(
// scrollDirection: Axis.horizontal,
children: [
ChangeNotifierProvider(
create: (_) => UserDataNotifier(),
child: _InternalWidget()
)
],
);
}
}
class _InternalWidget extends StatelessWidget {
const _InternalWidget({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
//
final _provider = context.watch<UserDataNotifier>();
final _model = _provider.userModel;
if (_model.isEmpty) {
return const SizedBox.shrink();
}
final _dtSource = UserDataTableSource(
userData: _model,
);
return PaginatedDataTable(
source: _dtSource,
horizontalMargin: 10,
columnSpacing: 10,
showFirstLastButtons: true,
rowsPerPage: PaginatedDataTable.defaultRowsPerPage,
columns: const [
DataColumn(
label: Text("Name"),
),
DataColumn(
label: Text("User Name"),
),
DataColumn(
label: Text("E-mail"),
),
DataColumn(
label: Text("Address"),
),
DataColumn(
label: Text("Phone"),
),
DataColumn(
label: Text("Website"),
),
DataColumn(
label: Text("Company"),
)
],
);
}
}
推荐阅读
- amazon-web-services - 上传到 S3 时的 EntityTooSmall
- javascript - 如何在 ng-repeat 中为多个 Select 填充动态选项
- python-3.x - GUI 应用程序在启动套接字服务器时停止
- python - 如何识别 Django 中 NoReverseMatch 错误的来源?
- c++ - 访问冲突抛出异常:写访问冲突。window.vertexBuffer 为 0x1110112
- django - 通过外键查询数据库
- git - Git将更改从一个远程推送到另一个
- spring-boot - 关于 Spring Data Flow Server 的困惑
- android - 如何在应用程序中读取 FirebaseDatabase DEBUG 日志?
- ruby-on-rails - Rails/Postgres Concat JSONB 键一起选择