Provider生命周期
什么时候创建并销毁我的Provider?
所有不同类型的provider经历的状态是相同的:
- 未初始化
- 活动中
- 暂停
- 已销毁
已销毁 / 未初始化
未初始化或已销毁的provider不占用任何内存,因为它的状态没有初始化。 从本质上来说,它只是定义了在你需要时如何创建provider的状态。 它将一直保持这种状态,直到活动中provider被创建或由于UI中的WidgetRef 读取、观察或监听它。
创建中 -> 活动中
当读取、监听或观察未初始化的provider时,将创建其状态。
在创建期间,你的provider的构建函数将会运行。
使用回调函数所暴露的 ref
读取(read)或观察(watch)的任何provider将根据需要创建,并且将检索它们的状态。
如果在创建过程中存在任何循环依赖关系,Riverpod将抛出一个错误。 修复此错误的最佳方式是重新设计依赖项,使其具有单向数据流。
provider的状态存储在 ProviderContainer 中。在Flutter应用中,此容器位于ProviderScope widget中。
因此,尽管如何创建状态(provider)的定义是全局的,但状态实际上是本地的, 并且使用嵌套的ProviderScope widget和覆盖在UI的不同部分中有所不同。
这与flutter widget的工作方式非常相似。你只需为其定义一次, 但是可以根据需要在树的不同部分重用状态。
活动中
当你的provider为活动中时,对其状态的更改将导致依赖的provider和/或依赖的UI重新构建。
从另一个角度来看,作为响应式框架,你可以观察其他provider,以便在它的某个依赖项发生变化时重建自己。
如果你需要一些依赖于其他状态的长期状态,你可以使用Ref的 listen 方法来订阅另一个provider上的更改,而不会导致重新构建该provider。
如果你需要使用来自另一个可能有副作用的provider的状态,你可以使用Ref的[read]方法从另一个provider获取当前状态。
通常,在构造 StateNotifier 或 ChangeNotifier 类时,应该传入引用, 以允许Notifier根据需要获取依赖项的当前值。 通过使用来自Riverpod 2.0的新Notifier 和 AsyncNotifier类,ref已经作为类的实例成员可用。
活动中 -> 暂停
当其他provider或UI不再监听活动的 provider时,它将进入暂停状态。这意味着它将不再对正在监听的provider的更改做出反应。 这是一种优化,如果你没有监听的provider,就没有必要让它保持活动状态。每个未被使用的provider都将返回到暂停状态,从而减少你的应用的计算负担。
如果你需要让provider保持活动状态以防止副作用发生,请确保在UI中应该保持活动状态的适当位置监听它。
如果你需要在provider暂停时执行一些操作,请使用ref的 onCancel 方法来注册回调函数。
当provider从暂停状态恢复到活动状态时,如果你需要执行一些操作,请使用ref的onResume方法来注册回调。
如果你想销毁状态,那么除了不占用计算资源外,还可以销毁状态的内存,请在provider上使用.autoDispose
修饰符。
这将导致它在不再被使用时转换到已销毁状态,而不是暂停状态。
活动中 -> 销毁中
销毁provider有几个原因。
- 当使用
.autoDispose
修饰符定义并不再被UI或其他providerg观察时 - 当手动刷新或provider失效时
- 当provider由于被监视的依赖项之一发生变化而被重新创建时
刷新会导致provider立即再次执行创建过程,而无效则会导致provider的下一次读取/观察导致重新构建provider。
在状态被销毁前执行操作
如果你需要在销毁provider时执行一些操作,使用ref的 onDispose 方法来注册回调函数。
下面的例子使用onDispose关闭StreamController:
Stream<int> example(ExampleRef ref) {
final streamController = StreamController<int>();
ref.onDispose(() {
// Closes the StreamController when the state of this provider is destroyed.
streamController.close();
});
return streamController.stream;
}
根据所使用的provider,它可能已经处理了清理过程。
例如,StateNotifierProvider 将调用返回的 StateNotifier 的dispose
方法。