Flutter中不使用StreamBuilder、Widget及.listen如何从Stream获取数据?
在不使用StreamBuilder和.listen的前提下,给PaginatedDataTable的DataTableSource传入Stream数据
问题背景
使用PaginatedDataTable组件时,需要将从Cloud Firestore读取的Stream数据传入自定义的MyData类(继承自DataTableSource)。参考示例是在MyData内部生成数据,但实际数据从外部Stream获取,且不能使用StreamBuilder(或其他Widget)和.listen方法。
现有代码
原StreamBuilder使用代码
StreamBuilder<List<Model>>( stream: stream, builder: (context, snapshot) { return snapshot.data == null ? Container() : PaginatedDataTable( source: MyData(list: snapshot.data!), columns: [ DataColumn( label: Text( "Name", maxLines: 1, overflow: TextOverflow.ellipsis, ), ), DataColumn( label: Text( "Email", maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], columnSpacing: 20, horizontalMargin: 10, rowsPerPage: 10, showCheckboxColumn: false, ); }, ),
原MyData类代码
class MyData extends DataTableSource { MyData({required this.list}) : super(); final List<Model> list; @override bool get isRowCountApproximate => false; @override int get rowCount => list.length; @override int get selectedRowCount => 0; @override DataRow getRow(int index) { return DataRow( cells: [ DataCell( Text( list[index].name, ), ), DataCell( Text( list[index].email, ), ), ], ); } }
解决方案
利用Dart的await for异步循环处理Stream数据,结合DataTableSource的notifyListeners()方法刷新表格,无需使用StreamBuilder或.listen:
修改后的MyData类
class MyData extends DataTableSource { // 直接接收Stream而非List MyData({required this.stream}) { // 初始化时启动Stream监听 _initStreamListener(); } final Stream<List<Model>> stream; List<Model> _dataList = []; // 异步初始化方法,用await for处理Stream Future<void> _initStreamListener() async { try { // 循环接收Stream的每个数据事件 await for (final newData in stream) { _dataList = newData; // 通知表格数据更新,触发刷新 notifyListeners(); } } catch (e) { // 处理Stream可能出现的错误 print('Stream error: $e'); } } @override bool get isRowCountApproximate => false; @override int get rowCount => _dataList.length; @override int get selectedRowCount => 0; @override DataRow getRow(int index) { return DataRow( cells: [ DataCell(Text(_dataList[index].name)), DataCell(Text(_dataList[index].email)), ], ); } }
修改后的PaginatedDataTable使用代码
无需再用StreamBuilder,直接传入Stream给MyData:
PaginatedDataTable( source: MyData(stream: stream), columns: [ DataColumn( label: Text( "Name", maxLines: 1, overflow: TextOverflow.ellipsis, ), ), DataColumn( label: Text( "Email", maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], columnSpacing: 20, horizontalMargin: 10, rowsPerPage: 10, showCheckboxColumn: false, ),
说明
await for是Dart原生的异步循环语法,不属于Stream的.listen方法,符合需求。- 每次Stream推送新数据时,更新内部的
_dataList并调用notifyListeners(),这是DataTableSource提供的方法,会自动触发PaginatedDataTable刷新行数据。 - 注意处理Stream的错误和生命周期,确保在页面销毁时关闭Stream,避免内存泄漏。
内容的提问来源于stack exchange,提问作者My Car
相关产品推荐
相关产品推荐

