[英]Flutter PaginatedDataTable Future failed with chained request
I have a problem with my PaginatedDataTable in Flutter Web (1.20.0-8.0.pre2): I have to chain two future request, one depending of the first.我在 Flutter Web (1.20.0-8.0.pre2) 中的 PaginatedDataTable 有问题:我必须链接两个未来的请求,一个取决于第一个。 For the example: First request return a json array of tasks:例如:第一个请求返回一个 json 任务数组:
[ ["field1", "field2", 154631565, "field4"],["field5", "field6", 7862626, "field8"] ]"
Number in 3d position is an id of a user. 3d position 中的数字是用户的 id。 The second request fetch the user with this is:使用此获取用户的第二个请求是:
[ 154631565, "John", "Doe"]
My code is based on this: https://github.com/AseemWangoo/experiments_with_web/tree/master/lib/data_table and https://flatteredwithflutter.com/using-paginateddatatable-in-flutter-web/我的代码基于此: https://github.com/AseemWangoo/experiments_with_web/tree/master/lib/data_table和https://flatteredwithflutter.com/using-paginateddatatable-in-flutter-web/
If I request only the first endpoint, all works, but I have Ids in the table rather than Name and First Name.如果我只请求第一个端点,一切正常,但我在表中有 Id,而不是 Name 和 First Name。
TaskDataTableAPi:任务数据表API:
class TaskDataTableApi {
TaskDataTableApi._();
static Future<List<TaskModel>> fetchData() async {
final _completer = Completer<List<TaskModel>>();
try {
final response = await http.get(_query);
if (response.statusCode == 200) {
// print(response.body);
final _data = taskModelFromJson(response.body.replaceAll(r'\t', ' '));
_completer.complete(_data);
} else {
print('Error, Could not load Data');
throw Exception('Failed to load Data');
}
} catch (exc) {
_completer.completeError(<TaskModel>[]);
}
return _completer.future;
}
}
UserDataTableApi:用户数据表接口:
class UserDataTableApi {
UserDataTableApi._();
static Future<List<UserModel>> fetchData(maxRows) async {
final _completer = Completer<List<UserModel>>();
String _query = url;
_query += 'selectQuery?loginName=' + loginName;
_query += '&password=' + password;
_query += '&custId=' + custId;
_query += '&maxRows= ' + maxRows;
_query += '&output=json&';
_query += 'query=SELECT id, firstName,lastName, photo FROM USER';
try {
final response = await http.get(_query);
if (response.statusCode == 200) {
print(response.body);
final _data = userModelFromJson(response.body.replaceAll(r'\t', ' '));
_completer.complete(_data);
} else {
print('Error, Could not load Data');
throw Exception('Failed to load Data');
}
} catch (exc) {
_completer.completeError(<UserModel>[]);
}
return _completer.future;
}
static Future<List<UserModel>> getOneById(int id) async {
final _completer = Completer<List<UserModel>>();
try {
final response = await http.get(_query);
if (response.statusCode == 200) {
//print(response.body);
final _data = userModelFromJson(response.body.replaceAll(r'\t', ' '));
_completer.complete(_data);
} else {
print('Error, Could not load Data');
throw Exception('Failed to load Data');
}
} catch (exc) {
_completer.completeError(<UserModel>[]);
}
return _completer.future;
}
}
TaskDataTableNotifier任务数据表通知程序
class TaskDataNotifier with ChangeNotifier {
TaskDataNotifier() {
fetchData();
}
List<TaskModel> get taskModel => _taskModel;
int get sortColumnIndex => _sortColumnIndex;
set sortColumnIndex(int sortColumnIndex) {
_sortColumnIndex = sortColumnIndex;
notifyListeners();
}
bool get sortAscending => _sortAscending;
set sortAscending(bool sortAscendindg) {
_sortAscending = sortAscending;
notifyListeners();
}
int get rowsPerPage => _rowsPerPage;
set rowsPerPage(int rowsPerPage) {
_rowsPerPage = rowsPerPage;
notifyListeners();
}
var _taskModel = <TaskModel>[];
int _sortColumnIndex;
bool _sortAscending = true;
int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage;
Future<void> fetchData() async {
_taskModel = await TaskDataTableApi.fetchData();
for (TaskModel _row in _taskModel) {
if (_row.dev != null) {
print(_row.dev);
// List<UserModel> _user = await UserDataTableApi.getOneById(_row.dev);
// print(_user[0].firstName);
}
}
notifyListeners();
}
}
and the page with DataTable:和带有数据表的页面:
class MyTasksList extends StatelessWidget {
const MyTasksList({Key key}) : super(key: key);
static const String routeName = '/tasks';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: MyAppBar(),
drawer: MyDrawer(),
body: ChangeNotifierProvider<TaskDataNotifier>(
create: (_) => TaskDataNotifier(),
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Center(
child: Container(
width: 1500.0,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.only(
top: 10.0,
),
child: _MyTasksList(),
),
],
),
),
),
),
),
);
}
}
class _MyTasksList extends StatelessWidget {
@override
Widget build(BuildContext context) {
final _provider = context.watch<TaskDataNotifier>();
final _model = _provider.taskModel;
if (_model.isEmpty) {
return const SizedBox.shrink();
}
final _dtSource = TaskDataTableSource(
//onRowSelect: (index) => _showDetails(context, _model[index]),
onRowSelect: (index) => print("Pressed"),
taskData: _model,
);
return PaginatedDataTable(
actions: <IconButton>[
IconButton(
splashColor: Colors.transparent,
icon: const Icon(Icons.refresh),
onPressed: () {
_provider.fetchData();
_showSBar(context, "Refresh successful");
},
),
],
header: Text('Task List'),
columns: myColumns(_dtSource, _provider),
source: _dtSource,
onRowsPerPageChanged: (rowsPerPage) {
_provider.rowsPerPage = rowsPerPage;
},
sortAscending: _provider.sortAscending,
sortColumnIndex: _provider.sortColumnIndex,
rowsPerPage: _provider.rowsPerPage,
);
}
List<DataColumn> myColumns(
TaskDataTableSource _src,
TaskDataNotifier _provider,
) =>
<DataColumn>[
DataColumn(
label: Text('Type'),
onSort: (colIndex, asc) {
_sort<num>((task) => task.taskType, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('Name'),
onSort: (colIndex, asc) {
_sort<String>((task) => task.name, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('?'),
),
DataColumn(
label: Text('Origin'),
onSort: (colIndex, asc) {
_sort<num>(
(task) => task.customerId, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('Customer'),
onSort: (colIndex, asc) {
_sort<num>(
(task) => task.customerId, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('Complexity'),
onSort: (colIndex, asc) {
_sort<num>(
(task) => task.complexity, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('Value'),
onSort: (colIndex, asc) {
_sort<num>((task) => task.value, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('Dev'),
onSort: (colIndex, asc) {
_sort<num>((task) => task.dev, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('Corr'),
// onSort: (colIndex, asc) {
// _sort<num>((task) => task.cor, colIndex, asc, _src, _provider);
// },
),
DataColumn(
label: Text('Status'),
),
DataColumn(
label: Text('Created on'),
onSort: (colIndex, asc) {
_sort<DateTime>(
(task) => task.createdOn, colIndex, asc, _src, _provider);
},
),
DataColumn(
label: Text('Canceled on'),
),
DataColumn(
label: Text('Super Score'),
),
];
void _sort<T>(
Comparable<T> Function(TaskModel task) getField,
int colIndex,
bool asc,
TaskDataTableSource _src,
TaskDataNotifier _provider,
) {
_src.sort<T>(getField, asc);
_provider.sortAscending = asc;
_provider.sortColumnIndex = colIndex;
}
void _showSBar(BuildContext c, String textToShow) {
Scaffold.of(c).showSnackBar(
SnackBar(
content: Text(textToShow),
duration: const Duration(milliseconds: 2000),
),
);
}
}
I tried to call await then() in the notifier, I see second request is fired but then app fails.我试图在通知程序中调用 await then(),我看到第二个请求被触发,但随后应用程序失败。
Thanks for help.感谢帮助。
I finally found a way to do that.我终于找到了一种方法来做到这一点。 I change the main Widget in a Stateful widget, and add a FutureBuilder.我在一个有状态的小部件中更改了主小部件,并添加了一个 FutureBuilder。 I removed the Provider class and use setState() to perform action on the DataTable.我删除了 Provider class 并使用 setState() 对 DataTable 执行操作。 With that I can do multiple await and so have my full data.有了它,我可以做多次等待,我的完整数据也是如此。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.