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

GraphQL Flutter包缓存正确实现方案及有效性验证方法咨询

解决graphql-flutter缓存不生效的问题

我之前也踩过graphql-flutter缓存的坑,官方示例的默认配置确实容易让人误以为缓存没起作用,咱们一步步来调整配置,再教你怎么验证缓存是否正常工作。

一、修正缓存的核心配置

先看你提供的客户端初始化代码,OptimisticCache本身是没问题的,但要确保几个关键配置到位:

1. 确保dataIdFromObject能生成唯一标识

你用了typenameDataIdFromObject,这个默认函数会把对象的__typename和id(或_id)拼接成唯一ID,但有些GraphQL服务返回的主键字段可能不是id(比如自定义服务用uuid)。如果你的数据主键不是id,得自定义这个函数:

String customDataIdFromObject(Object object) {
  if (object is Map<String, dynamic>) {
    final String? typename = object['__typename'];
    // 替换成你实际的主键字段,比如uuid、userId等
    final String? id = object['id'] ?? object['uuid']; 
    if (typename != null && id != null) {
      return '$typename:$id';
    }
  }
  //  fallback到默认实现
  return typenameDataIdFromObject(object); 
}

然后在缓存配置里替换:

cache: OptimisticCache(
  dataIdFromObject: customDataIdFromObject,
),

2. 查询时指定正确的fetchPolicy

这是最容易忽略的点!默认的fetchPolicy是networkOnly——也就是每次都强制从网络拉取数据,自然不会用到缓存。你需要在Query组件或者useQuery钩子中指定合适的策略:

  • cacheFirst:优先用缓存,缓存没数据再请求网络(适合不需要实时更新的场景)
  • cacheAndNetwork:先返回缓存数据,同时后台请求更新缓存(适合要快速显示+实时更新的场景)
  • cacheOnly:只从缓存取数据(适合离线场景)

比如在Query组件里配置:

Query(
  options: QueryOptions(
    document: gql(/* 你的查询语句 */),
    fetchPolicy: FetchPolicy.cacheFirst, // 这是关键!
  ),
  builder: (QueryResult result, {VoidCallback? refetch, FetchMore? fetchMore}) {
    // 你的UI构建逻辑
  },
)

也可以全局设置默认策略,避免每个查询都重复配置:

final ValueNotifier<GraphQLClient> client = ValueNotifier<GraphQLClient>(
  GraphQLClient(
    cache: OptimisticCache(...),
    link: link,
    defaultPolicies: const DefaultPolicies(
      query: Policies(fetch: FetchPolicy.cacheFirst),
    ),
  ),
);

二、验证缓存是否生效的实用方法

1. 用调试工具查看缓存内容

开启客户端的调试模式,就能在Flutter DevTools里查看缓存数据:

GraphQLClient(
  cache: OptimisticCache(...),
  link: link,
  debug: true, // 开启调试模式
);

打开Flutter DevTools的「Inspect」面板,找到GraphQLProvider,就能查看缓存里存储的所有数据了。

2. 离线测试法

把设备/模拟器切换到离线模式,重新打开页面。如果能正常显示之前加载过的数据,说明缓存已经生效。

3. 打印请求日志验证

给HttpLink添加日志拦截器,看看是否真的发送了网络请求:

final HttpLink httpLink = HttpLink(
  uri: 'https://api.github.com/graphql',
);

// 添加日志拦截
final Link loggedLink = httpLink.transform(
  RequestLogger(
    logRequest: true,
    logResponse: true,
  ),
);

// 拼接链路时用loggedLink
Link link = authLink.concat(loggedLink);

如果缓存生效,使用cacheFirst策略时,第二次加载页面不会打印新的网络请求日志。

三、针对官方示例的额外注意点

如果官方示例里开启了ENABLE_WEBSOCKETS,WebSocketLink的默认策略可能会影响缓存,你可以给WebSocketLink单独设置策略,或者确保查询时的fetchPolicy优先级更高。另外,记得替换示例中的YOUR_TOKEN为有效的GitHub个人访问令牌,避免因请求失败误以为缓存没生效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:09:53