You need to enable JavaScript to run this app. Flutter ObjectBox使用Data Observers & Rx监听实体变更列表不刷新如何解决
优惠活动
大模型
产品
解决方案
定价
更多

Flutter ObjectBox使用Data Observers & Rx监听实体变更列表不刷新如何解决

Flutter ObjectBox 监听实体字段变更实现页面列表同步方案

原有代码不生效的核心原因

  • StreamSubscription订阅对象被GC回收:如果sub1是方法内的局部变量,方法执行完成后实例会被系统回收,后续无法收到回调,必须将其定义为页面State类的成员变量。
  • 变更未同步到数据库:如果仅修改了内存中InvoiceList实例的dispatch属性,没有调用box.put()方法将变更持久化到数据库,ObjectBox感知不到数据变更,不会触发监听回调。
  • 旧版本兼容问题:1.4.0以下版本的ObjectBox存在watch()方法触发异常的已知问题,需升级到最新稳定版。

正确实现代码

class DeliveryListPage extends StatefulWidget {
  const DeliveryListPage({super.key});

  @override
  State<DeliveryListPage> createState() => _DeliveryListPageState();
}

class _DeliveryListPageState extends State<DeliveryListPage> {
  // 订阅对象定义为类成员变量,避免被GC回收
  late StreamSubscription<Query<InvoiceList>> sub1;
  // 页面展示的列表数据
  List<InvoiceList> deliveryList = [];

  @override
  void initState() {
    super.initState();
    // 1. 构建查询条件,生成Query实例
    final Query<InvoiceList> query = deliveryListBox!
        .query(InvoiceList_.dispatch.equals(true))
        .build();
    // 2. 开启监听,triggerImmediately设为true会首次加载时主动触发回调拿到初始数据
    final Stream<Query<InvoiceList>> watchedQuery = query.watch(triggerImmediately: true);
    // 3. 订阅数据变更回调
    sub1 = watchedQuery.listen((Query<InvoiceList> latestQuery) {
      // 直接通过回调返回的query实例拿到最新数据,无需额外重复查询数据库
      setState(() {
        deliveryList = latestQuery.find();
      });
    });
  }

  @override
  void dispose() {
    // 页面销毁时取消订阅,避免内存泄漏
    sub1.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // 直接使用deliveryList渲染列表即可
    return ListView.builder(
      itemCount: deliveryList.length,
      itemBuilder: (context, index) => ListTile(title: Text(deliveryList[index].orderNo)),
    );
  }
}

可选优化:仅监听dispatch字段变更

如果需要忽略InvoiceList其他字段的变更,只在dispatch字段修改时才触发列表更新,可通过distinct方法对流做过滤:

final Stream<Query<InvoiceList>> watchedQuery = query.watch(triggerImmediately: true)
    .distinct((prevQuery, nextQuery) {
      final prevList = prevQuery.find();
      final nextList = nextQuery.find();
      // 列表长度变化直接判定为变更
      if (prevList.length != nextList.length) return false;
      // 逐行对比dispatch字段,只要有一个发生变更就触发更新
      for (int i = 0; i < prevList.length; i++) {
        if (prevList[i].dispatch != nextList[i].dispatch) return false;
      }
      // 所有数据的dispatch字段无变化,不触发回调
      return true;
    });

内容的提问来源于stack exchange,提问作者Pratik Butani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 18:27:01