Flutter中Firestore流式数据本地过滤失效问题修复咨询
修复Firestore数据本地过滤并更新DataTable的问题
已通过StreamBuilder从Firestore拉取数据到PaginatedDataTable,但点击按钮执行本地过滤时功能失效,需要实现点击按钮后本地过滤数据并更新DataTable,且不发起服务端查询。
问题根源
- 数据覆盖:StreamBuilder每次收到Firestore新数据时,会直接覆盖展示用列表,导致过滤结果被重置
- 初始化无效:
initState中filtreData = kasalarim的赋值无意义,此时kasalarim为空列表 - 逻辑倒置:当前代码试图用
filtreData过滤后赋值给kasalarim,但未保留全量原始数据,后续过滤无数据可用 - UI未同步:过滤后未确保PaginatedDataTable的数据源同步更新
解决方案
维护两个独立列表:
_originalData:存储从Firestore拉取的全量原始数据_displayData:存储当前展示的过滤/排序后数据
StreamBuilder仅更新原始数据,过滤操作基于原始数据执行,通过setState触发UI重建,确保表格始终使用展示数据作为数据源。
修改后的代码片段
主组件变量调整
bool sort = true; // 存储Firestore拉取的全量原始数据 List<Kasalar_object> _originalData = []; // 存储当前展示的过滤/排序后数据 List<Kasalar_object> _displayData = []; void onSortColumn(int columnIndex, bool ascending) { setState(() { sort = ascending; if (columnIndex == 0) { ascending ? _displayData.sort((a, b) => a.kasa_adi.compareTo(b.kasa_adi)) : _displayData.sort((a, b) => b.kasa_adi.compareTo(a.kasa_adi)); } }); } @override void initState() { super.initState(); }
StreamBuilder逻辑修改
StreamBuilder( stream: firestore.collection("Users") .doc(FirebaseAuth.instance.currentUser?.email) .collection("kasalar") .snapshots(), builder: (context, AsyncSnapshot<QuerySnapshot> snap) { if (snap.hasError) { return Text('Error = ${snap.error}'); } if (snap.hasData) { // 更新全量原始数据 _originalData = snap.data!.docs.map((e) => Kasalar_object.fromMap(e.data() as Map<String, dynamic>)).toList(); // 首次加载时初始化展示数据为原始数据副本 if (_displayData.isEmpty) { _displayData = List.from(_originalData); } final DataTableSource _all_kasa = MyKasaData(_displayData); return PaginatedDataTable( sortColumnIndex: 0, sortAscending: sort, columns: [ DataColumn( label: Text('Kasa Adi'), onSort: (columnIndex, ascending) => onSortColumn(columnIndex, ascending), ), DataColumn(label: Text('Para Birimi')), DataColumn(label: Text('Açılıs Bakiyesi')), DataColumn(label: Text('Oluşturulma Tarihi')), DataColumn(label: Text('Aktif/Pasif')), DataColumn(label: Text('İslemler')), ], source: _all_kasa, columnSpacing: width/15, // 修正原代码拼写错误:witdh → width ); } else { return Center(child: CircularProgressIndicator()); } }, ),
过滤按钮逻辑修正
OutlinedButton( style: ButtonStyle( shape: MaterialStateProperty.all(RoundedRectangleBorder( borderRadius: BorderRadius.circular(2.0), )), backgroundColor: MaterialStateProperty.all(Constants.lightblack), ), onPressed: () { setState(() { // 基于全量原始数据执行过滤,结果赋值给展示数据 _displayData = _originalData.where((element) => element.kasa_adi.contains("hat")).toList(); }); }, child: Text("Kasa Ekle"), )
MyKasaData类补全(必须实现DataTableSource所有抽象方法)
class MyKasaData extends DataTableSource { SideBarController sideBarController = Get.put(SideBarController()); final List<Kasalar_object> _data; MyKasaData(this._data); FirebaseFirestore _firestore = FirebaseFirestore.instance; @override DataRow getRow(int index) { return DataRow(cells: [ DataCell(Text(_data[index].kasa_adi)), DataCell(Text(_data[index].doviz_cinsi)), DataCell(Text(_data[index].acilis_bakiyesi)), DataCell(Text(_data[index].olusturulma_tarihi)), DataCell(Text(_data[index].aktivite)), DataCell(Text('操作')), // 补全原代码缺失的操作列单元格 ]); } @override bool get isRowCountApproximate => false; @override int get rowCount => _data.length; @override int get selectedRowCount => 0; }
内容的提问来源于stack exchange,提问作者Berkay Isıkoglu
相关产品推荐
相关产品推荐

