跳到主要内容

.autoDispose

一个常见的用例是当不再使用provider时销毁它的状态。

这么做有很多原因,比如:

  • 使用Firebase时,关闭连接,避免不必要的开销。
  • 当用户离开页面并重新进入时重置状态。

Provider内置了 .autoDispose 修饰符来支持这些功能。

用法

要告诉Riverpod在provider不再使用时销毁它的状态, 只需将 .autoDispose 附加到你的provider上:

final userProvider = StreamProvider.autoDispose<User>((ref) {

});

就是这样。当不再使用 userProvider 时,它的状态将自动被销毁。

注意泛型参数是在autoDispose之后而不是之前传递的 —— autoDispose 不是一个命名构造器。

备注

如果你想,你也可以结合 .autoDispose 和其他修饰符:

final userProvider = StreamProvider.autoDispose.family<User, String>((ref, id) {

});

ref.keepAlive

使用 autoDispose 的 provider还会添加一个额外的方法到 ref 上: keepAlive

keepAlive 函数用于告诉Riverpod即使不再监听provider的状态也应该保留。

一个用例是在HTTP请求完成后将此标志设置为 true

final myProvider = FutureProvider.autoDispose((ref) async {
final response = await httpClient.get(...);
ref.keepAlive();
return response;
});

这样,如果请求失败,用户离开页面,然后重新进入,那么请求将再次执行。 但是如果请求成功完成,状态将被保留,重新进入就不会触发新的请求。

信息

在1.0.x的版本中, maintainState 属性等价于 keepAlive

示例:取消不再使用的HTTP请求

autoDispose 修饰符可以与 FutureProviderref.onDispose 结合使用, 以便在不再需要HTTP请求时轻松取消它们。

目标:

  • 当用户进入一个页面时启动一个HTTP请求
  • 如果用户在请求完成前离开页面,则取消HTTP请求
  • 如果请求成功,离开并重新进入页面则不会开始新的请求

下面是代码示例:

final myProvider = FutureProvider.autoDispose((ref) async {
// 来自package:dio的一个对象,允许取消http请求
final cancelToken = CancelToken();
// 当provider被销毁时,取消http请求
ref.onDispose(() => cancelToken.cancel());

// 获取我们的数据并传递“cancelToken”来取消工作
final response = await dio.get('path', cancelToken: cancelToken);
// 如果请求成功完成,则保持该状态
ref.keepAlive();
return response;
});

参数类型 'AutoDisposeProvider' 不能被赋值给参数类型 'AlwaysAliveProviderBase'

当使用 .autoDispose 时,你可能会发现你的应用在编译时出现类似错误:

The argument type 'AutoDisposeProvider' can't be assigned to the parameter type 'AlwaysAliveProviderBase'

不要担心!这个错误是正常的。发生这种情况是因为你很可能编写了一个bug:

你试图在未标记 .autoDispose 的provider中监听标记了 .autoDispose 的provider,例如:

final firstProvider = Provider.autoDispose((ref) => 0);

final secondProvider = Provider((ref) {
// The argument type 'AutoDisposeProvider<int>' can't be assigned to the
// parameter type 'AlwaysAliveProviderBase<Object, Null>'
ref.watch(firstProvider);
});

我们不希望这样,因为它将导致 firstProvider 永远不会被销毁。

要解决这个问题,可以考虑用 .autoDispose 标记 secondProvider:

final firstProvider = Provider.autoDispose((ref) => 0);

final secondProvider = Provider.autoDispose((ref) {
ref.watch(firstProvider);
});