跳到主要内容

为什么选择 Riverpod?

什么是 Riverpod?

Riverpod(Provider 的异序词)是 Flutter/Dart 的反应式缓存框架。

Riverpod 使用声明式和反应式编程,为您处理应用程序的大部分逻辑。 它可以通过内置的错误处理和缓存来执行网络请求,同时在必要时自动重新获取数据。

动机

现代应用程序很少提供呈现其用户界面所需的所有信息。 相反,数据通常是从服务器异步获取的。

问题是,使用异步代码很困难。 尽管 Flutter 提供了一些创建状态变量并在更改时刷新 UI 的方法,但它仍然相当有限。 许多挑战仍未解决:

  • 异步请求需要在本地缓存,因为每当 UI 更新时就重新执行异步请求是不合理的。
  • 由于我们有一个缓存,如果我们不关心的话,我们的缓存可能会过时。
  • 我们还需要处理错误和加载状态。

大规模解决这些问题可能很困难,并且它们会受到大量功能的影响,例如:

  • 下拉刷新
  • 无限列表/上划加载
  • 键入时搜索
  • 对异步请求进行去抖动
  • 不再使用异步请求时取消异步请求
  • 乐观 UI (注:主动积极的更新 UI 以实现良好的用户体验)
  • 离线模式
  • ……

这些功能可能很难实现,但对于良好的用户体验至关重要。
然而,很少有软件包尝试直接解决这些问题,而且很多工作必须手动完成。

这就是 Riverpod 的用武之地。
Riverpod 试图通过提供一种新的、独特的业务逻辑编写方式来解决这些问题, 这种方式的灵感来自 Flutter 小部件。 在许多方面,Riverpod 可以与小部件相媲美,但仅限于状态管理。

使用这种新方法,这些复杂的功能大多是默认完成的。 剩下的就是专注于你的 UI。

不信?举个例子。 以下代码片段是使用 Riverpod 实现的 Pub.dev 客户端应用程序的简化版本。


// Fetches the list of packages from pub.dev

Future<List<Package>> fetchPackages(
Ref ref, {
required int page,
String search = '',
}) async {
final dio = Dio();
// Fetch an API. Here we're using package:dio, but we could use anything else.
final response = await dio.get<List<Object?>>(
'https://pub.dartlang.org/api/search?page=$page&q=${Uri.encodeQueryComponent(search)}',
);

// Decode the JSON response into a Dart class.
return response.data?.map(Package.fromJson).toList() ?? const [];
}

此代码片段是在处理错误/加载状态时,“键入时搜索”+“下拉刷新”+“无限列表”所需的所有业务逻辑。