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

Flutter使用provider包监听状态变化实现Widget自动重建的方法咨询

实现方案

你遇到的核心问题是local storage本身没有内置的变化监听能力,需要把业务数据存在Provider的可监听状态层,同时和local storage做双向同步即可,具体实现步骤如下:

1. 定义可监听的状态管理类

继承ChangeNotifier封装订阅数据的读写逻辑,所有对数据的修改都走这个类的方法,保证修改后可以通知UI更新。

import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';

// 可以替换成你自己的业务数据实体类,这里用通用结构做示例
typedef SubscriptionItem = Map<String, dynamic>;

class SubscribeDataNotifier extends ChangeNotifier {
  List<SubscriptionItem> _dataList = [];
  List<SubscriptionItem> get dataList => _dataList;

  // 初始化时从local storage拉取历史数据
  Future<void> init() async {
    final prefs = await SharedPreferences.getInstance();
    final cacheStr = prefs.getString('graphql_subscribe_cache');
    if (cacheStr != null) {
      // 此处替换为你自己的反序列化逻辑,把字符串转成业务数据结构
      // _dataList = 反序列化结果;
      notifyListeners();
    }
  }

  // 收到GraphQL推送新数据时调用该方法
  Future<void> addNewData(SubscriptionItem newItem) async {
    // 更新内存中的状态
    _dataList.add(newItem);
    // 同步写入local storage持久化
    final prefs = await SharedPreferences.getInstance();
    // 此处替换为你自己的序列化逻辑,把业务数据转成字符串存储
    // final cacheStr = 序列化结果;
    await prefs.setString('graphql_subscribe_cache', cacheStr);
    // 通知所有监听的Widget重建
    notifyListeners();
  }
}

2. 顶层注册Provider

在App入口把状态类注册到Widget树,全局可访问:

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => SubscribeDataNotifier()..init(),
      child: const MyApp(),
    ),
  );
}

3. GraphQL订阅回调中触发数据更新

在你的订阅逻辑里,收到后端推送的数据后,调用状态类的更新方法即可:

// 你的GraphQL订阅初始化逻辑
void initSubscribe(BuildContext context) {
  final client = GraphQLClient(/* 你的客户端配置 */);
  client.subscribe(SubscriptionOptions(
    document: gql('你的订阅查询语句'),
  )).listen((result) {
    if (result.hasException || result.data == null) return;
    final newItem = result.data!['订阅返回的字段名'];
    // 调用状态类更新方法
    context.read<SubscribeDataNotifier>().addNewData(newItem);
  });
}

4. UI层监听数据自动更新

需要展示数据的Widget中,用watch或者Consumer监听状态变化即可自动重建:

class DataListWidget extends StatelessWidget {
  const DataListWidget({super.key});

  @override
  Widget build(BuildContext context) {
    // 监听数据变化,数据更新时自动触发build
    final dataList = context.watch<SubscribeDataNotifier>().dataList;
    return ListView.builder(
      itemCount: dataList.length,
      itemBuilder: (context, index) {
        return ListTile(
          title: Text(dataList[index]['你要展示的字段名']),
        );
      },
    );
  }
}

注意:所有对这份订阅数据的读写都要走SubscribeDataNotifier的封装方法,不要在业务代码中直接操作SharedPreferences实例,否则会出现数据和UI不同步的问题。

内容的提问来源于stack exchange,提问作者EA vijay

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 15:57:04