Flutter 使用自定义ChangeNotifier初始化riverpod提供程序

Flutter 使用自定义ChangeNotifier初始化riverpod提供程序,flutter,flutter-provider,state-management,riverpod,flutter-hooks,Flutter,Flutter Provider,State Management,Riverpod,Flutter Hooks,我只是在尝试新的,弗利特州管理图书馆。我的目标很简单GestureDetector侦听垂直拖动并相应地更新动画控制器。我想在别的地方听这个动画。我已经编写了下面的代码,它按照预期工作。但我觉得我没有以正确的方式初始化提供程序 //自定义通知程序类 类AnimationNotifier扩展了ChangeNotifier{ 最终AnimationController _AnimationController; AnimationNotifier(此.\u animationController){

我只是在尝试新的,弗利特州管理图书馆。我的目标很简单<主页中的code>GestureDetector侦听垂直拖动并相应地更新动画控制器。我想在别的地方听这个动画。我已经编写了下面的代码,它按照预期工作。但我觉得我没有以正确的方式初始化提供程序

//自定义通知程序类
类AnimationNotifier扩展了ChangeNotifier{
最终AnimationController _AnimationController;
AnimationNotifier(此.\u animationController){
_animationController.addListener(\u onAnimationControllerChanged);
}
void forward()=>_animationController.forward();
void reverse()=>_animationController.reverse();
void _onAnimationControllerChanged(){
notifyListeners();
}
@凌驾
无效处置(){
_animationController.RemovelListener(_onAnimationControllerChanged);
super.dispose();
}
double get value=>\u animationController.value;
}
//提供程序变量(此处未初始化)
var动画提供者;
//主部件
类GestureControlled动画演示扩展StatefulWidget{
@凌驾
_GestureControlledAnimationDemoState createState()=>
_手势控制动画演示();
}
类\u GestureControlledAnimationDemoState
扩展状态
使用SingleTickerProviderStateMixin{
动画控制器_控制器;
double get maxHeight=>420.0;
@凌驾
void initState(){
_控制器=动画控制器(
vsync:这个,,
持续时间:常数持续时间(秒数:1),
);
//提供程序在此处初始化
animationProvider=ChangeNotifierProvider((){
返回AnimationNotifier(_控制器);
});
super.initState();
}
@凌驾
无效处置(){
_controller.dispose();
super.dispose();
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
标题:“手势控制”,
正文:手势检测器(
垂直DragUpdate:\u handleDragUpdate,
在垂直方向上:_handleDragEnd,
子:容器(
颜色:颜色,红色,
儿童:中心(
子:列(
mainAxisAlignment:mainAxisAlignment.center,
儿童:[
正文(
"哟",,
样式:TextStyle(颜色:Colors.white),
),
NotifierTest(),
],
),
),
),
),
);
}
void\u handleDragUpdate(DragUpdate详细信息){
_controller.value-=details.primaryDelta/maxHeight;
}
void_handleDragEnd(图纸详图){
如果(_)控制器正在初始化||
_controller.status==AnimationStatus.completed)返回;
最后双掷球=
details.velocity.pixelsPerSecond.dy/maxHeight;
如果(flingVelocity<0.0){
_控制器.fling(速度:最大值(2.0,-flingVelocity));
}否则如果(flingVelocity>0.0){
_控制器.fling(速度:min(-2.0,-flingVelocity));
}否则{
_控制器投掷(速度:_控制器值<0.5?-2.0:2.0);
}
}
}
//使用提供者的小部件
类NotifierTest扩展了HookWidget{
@凌驾
小部件构建(构建上下文){
最终animationNotifier=useProvider(animationProvider);
双重计数=animationNotifier.value*1000.0;
返回容器(
子:文本(
“${count.floor()}”,
样式:TextStyle(颜色:Colors.white),
),
);
}
}
由于创建
AnimationNotifier
的实例需要动画控制器实例,因此只有在
\u controller
初始化后才能执行此操作。因此,在
initState()
中,我已经初始化了
\u controller
animationProvider
。这是使用riverpod
提供商的正确方法吗?

如果没有,可以进行哪些修改?

首先,我强烈建议使用钩子-这将大大减少代码的样板,例如,您的类声明将变成:


类GestureControlledAnimationDemo扩展HookWidget{
double get maxHeight=>420.0;
@凌驾
小部件构建(构建上下文){
最终的_控制器=使用AnimationController(持续时间:持续时间(秒:1));
...
}
这样就不需要initState、dispose等

其次,您不一定要在类内创建非静态提供程序。相反,您可以在全局范围内创建它,或者在这种情况下,将其作为静态成员添加到自定义通知程序中是有意义的

class AnimationNotifier扩展了ChangeNotifier{
...
静态最终提供程序=ChangeNotifierProvider((){
返回动画通知程序(控制器);
});
}
但是,等等,我们在此范围内没有任何名为
controller
的变量,那么我们如何获得访问权限?我们可以为AnimationController创建一个提供程序,或者我们可以将您的提供程序转换为,以便我们可以接受AnimationController作为参数。我将演示使用族的方法:

class AnimationNotifier扩展了ChangeNotifier{
...
静态最终提供程序=ChangeNotifierProvider.autoDispose.family

编辑:

对于您的用例,您可能会将当前控制器存储在StateProvider中,然后从ChangeNotifierProvider读取它,而不是使用族

final controllerProvider=StateProvider(()=>null);
类AnimationNotifier扩展了ChangeNotifier{
...
静态最终提供程序=ChangeNotifierProvider.autoDispose((参考){
最终控制器=参考读取(控制器提供程序)?状态;
返回动画通知程序(控制器);
});
}

类GestureControlledAnimationDemo扩展HookWidget{
double get maxHeight=>420.0;
@凌驾
小部件构建(构建上下文){
最终控制器=useAnimationCo