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 构建器数据

如何使用 dart/flutter 从 API 获取数据?

Flutter:如何在加载页面之前从 Api 获取数据 [关闭]

Flutter 如何使用 JSON 从 Rest API 获取 List<String> _list 数组字符串

在 Flutter 中,我如何使用 API 和 GetX 在 JSON 中获取数据

Flutter 从 Api 获取 Userinfo 并在任何地方使用。请帮我