我想显示一个DataTable,其中数据输入根据用户的输入而变化(用户可以选择一个csv文件,然后其内容将显示在DataTable小部件中)。
我的问题是,根据用户的csv文件中的行和列数,创建DataTable可能需要花费几秒钟的时间,并且屏幕同时冻结,这显然是不好的用户体验。因此,我的想法是在单独的隔离区中创建DataTable,等待结果(请参见下面的代码),并在等待结果时显示CircularProgressIndicator。
不幸的是,这种方法不起作用(我认为是因为CustomDataTable不是有效的message type)。
我在这里使用隔离的方法可能是错误的(我是扑朔迷离的新手),如果可以引导我朝正确的方向前进,我很乐意转向另一种策略。
// In the class of my Stateful Widget that will display the CustomDataTable I have this function spawning the isolate and awaiting the CustomDataTable
Future<CustomDataTable> createCustomTableInIsolate(List<Map<String, String>> data, List<Map<String, String>> selectedRows, List<String> columnNames, Function onSelectedRow) async {
var map = {
'data': data,
'selectedRows': selectedRows,
'columnNames': columnNames,
'onSelectedRow': onSelectedRow,
};
CustomDataTable dataTable = await compute(createCustomTable, map);
return dataTable;
}
//... somewhere in my widget tree
FutureBuilder<CustomDataTable>(
future: createCustomTableInIsolate(),
builder: (BuildContext ctx,
AsyncSnapshot snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else if (!snapshot.hasData) {
return Center(
child: Text('Please check your input data...'),
);
} else {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: constraints.minWidth,
),
child: snapshot.data),
);
}
},
),
// ...
// Function creating the CustomDataTable in different isolate (outside of stateful widget class)
CustomDataTable createCustomTable(Map<String, dynamic> map) {
return CustomDataTable(
data: map['data'],
selectedRows: map['selectedRows'],
columnNames: map['columnNames'],
onSelectedRow: map['onSelectedRow'],
);
}
// Separate class to create the DataTable widget
class CustomDataTable extends StatelessWidget {
final List<Map<String, String>> data;
final List<Map<String, String>> selectedRows;
final List<String> columnNames;
final Function onSelectedRow;
CustomDataTable({
@required this.data,
@required this.selectedRows,
@required this.columnNames,
@required this.onSelectedRow,
});
@override
Widget build(BuildContext context) {
return DataTable(
columns: columnNames.map((columnName) {
return DataColumn(
label: Text(
columnName,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
);
}).toList(),
rows: data.map((column) {
var columnValues = column.values;
return DataRow(
selected: selectedRows.contains(column),
onSelectChanged: (selected) {
onSelectedRow(selected, column);
},
cells: columnValues.map((cellValue) {
return DataCell(
Text(
cellValue,
style: TextStyle(
color: Colors.white,
),
),
);
}).toList());
}).toList(),
);
}
}