能扑 PaginatedDataTable rowsPerPage 被设置为一个数字不是10整除?
更新
FutureBuilder使用的数据是从本地服务器获取的。首先,该列表包含3个项目,这将导致创建空的DataRows。
我的问题
我尝试过的
样本代码
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
我的DataTableSource
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; }