You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中Firestore流式数据本地过滤失效问题修复咨询

修复Firestore数据本地过滤并更新DataTable的问题

已通过StreamBuilder从Firestore拉取数据到PaginatedDataTable,但点击按钮执行本地过滤时功能失效,需要实现点击按钮后本地过滤数据并更新DataTable,且不发起服务端查询。

问题根源

  1. 数据覆盖:StreamBuilder每次收到Firestore新数据时,会直接覆盖展示用列表,导致过滤结果被重置
  2. 初始化无效:initState中filtreData = kasalarim的赋值无意义,此时kasalarim为空列表
  3. 逻辑倒置:当前代码试图用filtreData过滤后赋值给kasalarim,但未保留全量原始数据,后续过滤无数据可用
  4. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 05:35:02