flutter PaginatedDataTable rowsPerPage 可以设置为不能被 10 整除的数字吗?

更新

FutureBuilder 使用的数据是从本地服务器获取的。起初,该列表包含 3 个项目,这会导致创建空的 DataRow。

我的问题

  • 我不想创建空的 DataRows

  • 我试过的东西
  • 如果列表长度小于 defaultRowsPerPage,则将 rowsPerPage 计数设置为列表的长度,否则将其 (rowsPerPage) 设置为 defaultRowsPerPage。

  • 示例代码
    import 'package:flutter/material.dart';
    import 'package:nvip/constants.dart';
    import 'package:nvip/data_repo/network/centers_repo.dart';
    import 'package:nvip/data_repo/tables/data_source_centers.dart';
    import 'package:nvip/models/vaccination_center.dart';
    
    class VaccinationCentersTableScreen extends StatelessWidget {
      @override
      Widget build(BuildContext context) => _CentersScreenBody();
    }
    
    class _CentersScreenBody extends StatefulWidget {
      @override
      __CentersScreenBodyState createState() => __CentersScreenBodyState();
    }
    
    class __CentersScreenBodyState extends State<_CentersScreenBody> {
      int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage; // This one works
      int _columnIndex = 1;
      bool _isSortAscending = true;
      Future<List<VaccineCenter>> _centers;
      CentersTableDataSource _tableDataSource;
      var _scaffoldKey = GlobalKey<ScaffoldState>();
    
      void _sort<T>(Comparable<T> getField(VaccineCenter c), int columnIndex,
          bool isSortAscending) {
        _tableDataSource?.sort(getField, isSortAscending);
        setState(() {
          _columnIndex = columnIndex;
          _isSortAscending = isSortAscending;
        });
      }
    
      @override
      void initState() {
        super.initState();
        _centers = VaccineCentersDataRepo().getCenters();
      }
    
      @override
      Widget build(BuildContext context) {
        return WillPopScope(
          onWillPop: () {
            Navigator.pushReplacementNamed(context, Routes.keyHome);
          },
          child: Scaffold(
            key: _scaffoldKey,
            appBar: AppBar(
              title: Text("Vaccination Centers"),
              centerTitle: true,
              leading: IconButton(
                icon: Icon(Constants.backIcon),
                onPressed: () {
                  Navigator.pushReplacementNamed(context, Routes.keyHome);
                },
              ),
              actions: <Widget>[
                IconButton(
                  icon: Icon(Icons.add),
                  tooltip: "Add vaccination center",
                  onPressed: () {
                    Navigator.pushReplacementNamed(context, Routes.keyPovAdd);
                  },
                )
              ],
            ),
            body: FutureBuilder<List<VaccineCenter>>(
              future: _centers,
              builder: (context, snapshot) {
                if (snapshot.hasError) {
                  return Constants.showHasNoDataWidget(
                    context,
                    "No vaccination center(s) / place(s) of vaccinations found. "
                        "Press the (+) sign to add a new record.",
                  );
                } else {
                  if (snapshot.hasData) {
                    var centerList = snapshot.data;
                    var centersCount = centerList.length;
                    var defaultRowsPerPage = PaginatedDataTable.defaultRowsPerPage;
                    _rowsPerPage = centersCount < defaultRowsPerPage
                        ? centersCount
                        : defaultRowsPerPage;
                    _tableDataSource = CentersTableDataSource(centerList);
                    return SingleChildScrollView(
                      child: PaginatedDataTable(
                        header: Text("Places of Vaccination"),
                        rowsPerPage: _rowsPerPage,
                        onRowsPerPageChanged: (rowCount) {
                          setState(() {
                            _rowsPerPage = rowCount;
                          });
                        },
                        sortColumnIndex: _columnIndex,
                        sortAscending: _isSortAscending,
                        onSelectAll: (isAllChecked) =>
                            _tableDataSource?.selectAll(isAllChecked),
                        actions: <Widget>[
                          IconButton(
                            icon: Icon(Icons.add),
                            tooltip: "Add vaccination center",
                            onPressed: () {
                              Navigator.pushReplacementNamed(
                                  context, Routes.keyPovAdd);
                            },
                          ),
                          IconButton(
                            icon: Icon(Icons.delete_forever),
                            tooltip: "Delete vaccination center(s).",
                            onPressed: () {
                              Constants.showSnackBar(
                                  _scaffoldKey, "Delete button clicked");
                            },
                          )
                        ],
                        columns: <DataColumn>[
                          DataColumn(
                            label: Text("No."),
                            numeric: true,
                            onSort: (ci, isSortAscending) => _sort<num>(
                                (c) => centerList.indexOf(c), ci, isSortAscending),
                          ),
                          DataColumn(
                            label: Text("Name"),
                            onSort: (ci, isSortAscending) =>
                                _sort<String>((c) => c.name, ci, isSortAscending),
                          ),
                        ],
                        source: _tableDataSource,
                      ),
                    );
                  }
                }
    
                return Center(child: CircularProgressIndicator());
              },
            ),
          ),
        );
      }
    }
    

    错误日志
    I/flutter ( 8474): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
    I/flutter ( 8474): The following assertion was thrown building FutureBuilder<List<VaccineCenter>>(dirty, state:
    I/flutter ( 8474): _FutureBuilderState<List<VaccineCenter>>#92379):
    I/flutter ( 8474): 'package:flutter/src/material/paginated_data_table.dart': Failed assertion: line 87 pos 19:
    I/flutter ( 8474): 'availableRowsPerPage != null && availableRowsPerPage.contains(rowsPerPage)': is not true.
    I/flutter ( 8474):
    I/flutter ( 8474): Either the assertion indicates an error in the framework itself, or we should provide substantially
    I/flutter ( 8474): more information in this error message to help you determine and fix the underlying cause.
    I/flutter ( 8474): In either case, please report this assertion by filing a bug on GitHub:
    I/flutter ( 8474):   https://github.com/flutter/flutter/issues/new?template=BUG.md
    I/flutter ( 8474):
    I/flutter ( 8474): When the exception was thrown, this was the stack:
    I/flutter ( 8474): #2      new PaginatedDataTable.<anonymous closure> (package:flutter/src/material/paginated_data_table.dart:87:19)
    I/flutter ( 8474): #3      new PaginatedDataTable (package:flutter/src/material/paginated_data_table.dart:89:9)
    I/flutter ( 8474): #4      __CentersScreenBodyState.build.<anonymous closure> (package:nvip/scenes/vaccination_centers/screen_center_table.dart:86:26)
    I/flutter ( 8474): #5      _FutureBuilderState.build (package:flutter/src/widgets/async.dart)
    I/flutter ( 8474): #6      StatefulElement.build (package:flutter/src/widgets/framework.dart:3809:27)
    I/flutter ( 8474): #7      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3721:15)
    I/flutter ( 8474): #8      Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
    I/flutter ( 8474): #9      BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2286:33)
    I/flutter ( 8474): #10     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:676:20)
    I/flutter ( 8474): #11     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:219:5)
    I/flutter ( 8474): #12     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
    I/flutter ( 8474): #13     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
    I/flutter ( 8474): #14     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5)
    I/flutter ( 8474): #15     _invoke (dart:ui/hooks.dart:154:13)
    I/flutter ( 8474): #16     _drawFrame (dart:ui/hooks.dart:143:3)
    I/flutter ( 8474): (elided 2 frames from class _AssertionError)
    I/flutter ( 8474): ════════════════════════════════════════════════════════════════════════════════════════════════════
    

    更新 2

    我的数据表源
    import 'package:flutter/material.dart';
    import 'package:nvip/models/vaccination_center.dart';
    
    class CentersTableDataSource extends DataTableSource {
      final List<VaccineCenter> _centers;
      int _rowsSelectedCount = 0;
    
      CentersTableDataSource(this._centers);
    
      @override
      DataRow getRow(int index) {
        assert(index >= 0);
        if (index >= _centers.length) return null;
        final VaccineCenter center = _centers[index];
        return DataRow.byIndex(
          index: index,
          selected: center.isSelected,
          onSelectChanged: (selected) {
            if (center.isSelected != selected) {
              _rowsSelectedCount += selected ? 1 : -1;
              center.isSelected = selected;
              notifyListeners();
            }
          },
          cells: <DataCell>[
            DataCell(Text("${index + 1}")),
            DataCell(Text(center.name)),
          ],
        );
      }
    
      @override
      bool get isRowCountApproximate => false;
    
      @override
      int get rowCount => _centers.length;
    
      @override
      int get selectedRowCount => _rowsSelectedCount;
    
      void sort<T extends Object>(
          Comparable<T> getField(VaccineCenter d), bool isAscending) {
        _centers.sort((a, b) {
          if (isAscending) {
            final VaccineCenter c = a;
            a = b;
            b = c;
          }
    
          final Comparable<T> aValue = getField(a);
          final Comparable<T> bValue = getField(b);
          return Comparable.compare(aValue, bValue);
        });
        notifyListeners();
      }
    
      void selectAll(bool isAllChecked) {
        _centers.forEach((center) => center.isSelected = isAllChecked);
        _rowsSelectedCount = isAllChecked ? _centers.length : 0;
        notifyListeners();
      }
    }
    

    最佳答案

      import 'package:flutter/material.dart';
    
        class DemoTable extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
            return _DemoTableBody();
          }
        }
    
        class _DemoTableBody extends StatefulWidget {
          @override
          __DemoTableBodyState createState() => __DemoTableBodyState();
        }
    
        class __DemoTableBodyState extends State<_DemoTableBody> {
    
          int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage;
    
          // A Variable to hold the length of table based on the condition of comparing the actual data length with the PaginatedDataTable.defaultRowsPerPage
    
          int _rowsPerPage1 = PaginatedDataTable.defaultRowsPerPage;
    
          @override
          Widget build(BuildContext context) {
    
          //Obtain the data to be displayed from the Derived DataTableSource
    
            var dts = DTS();
    
            // dts.rowcount provides the actual data length, ForInstance, If we have 7 data stored in the DataTableSource Object, then we will get 12 as dts.rowCount
    
           var tableItemsCount = dts.rowCount;
    
            // PaginatedDataTable.defaultRowsPerPage provides value as 10
    
            var defaultRowsPerPage = PaginatedDataTable.defaultRowsPerPage;
    
            // We are checking whether tablesItemCount is less than the defaultRowsPerPage which means we are actually checking the length of the data in DataTableSource with default PaginatedDataTable.defaultRowsPerPage i.e, 10
    
            var isRowCountLessDefaultRowsPerPage = tableItemsCount < defaultRowsPerPage;
    
            // Assigning rowsPerPage as 10 or acutal length of our data in stored in the DataTableSource Object
    
            _rowsPerPage =
                isRowCountLessDefaultRowsPerPage ? tableItemsCount : defaultRowsPerPage;
            return Scaffold(
              appBar: AppBar(
                title: Text("Demo Paginated Table"),
              ),
              body: SingleChildScrollView(
                child: PaginatedDataTable(
                  header: Text('data with 7 rows per page'),
                  // comparing the actual data length with the PaginatedDataTable.defaultRowsPerPage and then assigning it to _rowPerPage1 variable which then set using the setsState()
                  onRowsPerPageChanged: isRowCountLessDefaultRowsPerPage // The source of problem!
                      ? null
                      : (rowCount) {
                          setState(() {
                            _rowsPerPage1 = rowCount;
                          });
                        },
                  columns: <DataColumn>[
                    DataColumn(label: Text('row')),
                    DataColumn(label: Text('name')),
                  ],
                  source: dts,
                  //Set Value for rowsPerPage based on comparing the actual data length with the PaginatedDataTable.defaultRowsPerPage
                  rowsPerPage:
                      isRowCountLessDefaultRowsPerPage ? _rowsPerPage : _rowsPerPage1,
                ),
              ),
            );
          }
        }
    
        class DTS extends DataTableSource {
          @override
          DataRow getRow(int index) {
            return DataRow.byIndex(
              index: index,
              cells: [
                DataCell(Text('row #$index')),
                DataCell(Text('name #$index')),
              ],
            );
          }
    
          @override
          int get rowCount => 9; // Manipulate this to which ever value you wish
    
          @override
          bool get isRowCountApproximate => false;
    
          @override
          int get selectedRowCount => 0;
        }
    

    10-06 08:03