Flutter:如何从 api 获取数据并在 PaginatedDataTable 中绑定
Posted
技术标签:
【中文标题】Flutter:如何从 api 获取数据并在 PaginatedDataTable 中绑定【英文标题】:Flutter: How to get data from api and bind in PaginatedDataTable 【发布时间】:2021-10-19 00:52:06 【问题描述】: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]。
【问题讨论】:
【参考方案1】:您需要的是一个更改通知器。
让我们做一个简单的例子。
这是我的模型:
"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"),
)
],
);
【讨论】:
以上是关于Flutter:如何从 api 获取数据并在 PaginatedDataTable 中绑定的主要内容,如果未能解决你的问题,请参考以下文章
如何使用提供程序在 Flutter ui 中使用 api 响应获取 ListView 构建器数据
Flutter:如何在加载页面之前从 Api 获取数据 [关闭]
Flutter 如何使用 JSON 从 Rest API 获取 List<String> _list 数组字符串