.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
修饰符可以与 FutureProvider 和 ref.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);
});