跳转到内容
Fuery 标志,三块圆角方块组成字母 FFuery 标志,三块圆角方块组成字母 F

Fuery

在 Flutter 中获取、缓存服务端数据,并让它保持新鲜。
// A Query<List<Todo>>, with no type arguments.
final todos = Query(
queryKey: ['todos'],
queryFn: (_) => api.getTodos(),
);
QueryBuilder(
query: todos,
builder: (context, state) => switch (state.data) {
final data? => TodoList(data), // a List<Todo>
null => const CircularProgressIndicator(),
},
)

Flutter 中的服务端状态解释服务端数据为什么需要缓存。变更创建、更新和删除服务端数据,并支持乐观更新。

以 Flutter 的方式构建

显示查询的界面仍然是 StatelessWidget。查询定义在 build 之外,widget 像 StreamBuilder 渲染 stream 那样渲染查询:构建器负责 UI,监听器负责副作用。逐个界面引入 Fuery,无须替换任何东西。使用 hook 时,独立的包 fuery_hooks 用 useQuery 渲染同样的查询。

只需 Dart 和 Flutter

没有代码生成,没有原生代码,也没有平台配置。核心是纯 Dart 代码,只依赖 Dart 团队的 clock、collection 和 meta。widget、cubit、bloc、服务、CLI 和服务器使用同一个查询对象。

有缓存,也保持新鲜

使用同一个键的所有 widget 共享一个缓存条目和一个请求。Fuery 在后台重新获取过期数据时,过期数据仍然显示在屏幕上。重新获取返回的列表项按 == 相等时,Fuery 保留之前的对象,因此这些列表行不会重建。

类型来自你的函数

查询、变更和无限查询从各自的函数获得类型。widget、结果和回调无须类型参数就带有这些类型。有两种情况需要写明类型:只按键读取或写入,例如 getQueryData<List<Todo>>(['todos']);以及第一个页参数为 null 的无限查询。

为真实网络而构建

屏幕上的查询在获取失败时以退避方式重试 3 次,并在应用回到前台时重新获取。接入网络状态来源后,查询在设备离线时暂停,在网络重新连接时重新获取。对于读取 context.signal 的查询函数,Fuery 在不再有地方使用它时取消它,并且不把这次取消报告为错误。查询可以一直轮询到某个条件成立,也可以把 stream 累积到缓存中。

可持久化,可检查

持久化的查询在应用重启后依然保留,可以使用任何键值存储。开发者工具在设备上运行的应用中显示缓存。

经过测试。每个包都有 100% 的行覆盖率,任何一行失去覆盖时 CI 都会失败。测试在支持的最低 Flutter 版本(3.27)和最新版本上运行。核心的测试在模拟时间下运行。回归测试套件让已修复的边界情况保持修复状态。Fuery 在销毁路径上取消所有计时器,并从 package:clock 读取时间,因此你自己的 fake_async 测试和 widget 测试不会泄漏计时器。参见测试。

Fuery 的缓存和重新获取模型受 TanStack Query 启发。写给 TanStack Query 用户列出了它的每个概念在 Fuery 中的名称。