Rive 和 Riverpod 的清洁解决方案

Clean solution for Rive and Riverpod

在我的 flutter 应用程序中,我想将 Rive 用于动画,将 Riverpod 用于状态管理。所以现在我正在寻找一种高效的方式来监听我的提供者的状态来管理我的 SMIInput<bool> 的状态。目前我用消费者包装 Rive 小部件,从 riverpod 获取状态并设置控制器值。

Consumer(builder: (context, watch, _) {
  _smile?.value = watch(widget._stateRef).smile;
  return Rive(
    artboard: _riveArtboard!,
  );
});

我想这会在 _smile.value 设置后运行 Rive 小部件的构建方法,一旦它 returns 小部件。

- 我做对了吗?

出于这个目的,我尝试调用 addListener 到提供者通知程序以在那里设置 _smile.value

context.read(widget._stateRef.notifier).addListener((logoState) {
   if (mounted) {
     _smile?.value = logoState.smile;
   }
});

但这只运行一次,而不是像我希望的那样在每次状态更改时运行。

- 是否有其他建议无需使用 Consumer 即可更改控制器输入值?

final signInLogoSmileProvider =
    StateNotifierProvider<LogoNotifier, LogoState>((ref) {
  // ignore: unused_local_variable
  ref.watch(signInFormProvider);
  final signInFormNotifier = ref.read(signInFormProvider.notifier);
  return LogoNotifier(smile: signInFormNotifier.shouldSmile);
});

我需要观察 signInFormProviders 状态而不是 signInFormProvider.notifiers 状态,因为 addListeners 只运行一次。

- 这是不好的做法,还是我做错了什么?

如果您有任何好的 Rive 和 Riverpod 携手合作,我将不胜感激。

我正在使用较新版本的 Riverpod 和 Rive,但您可以通过使用 ConsumerStatefulWidget 轻松完成,然后使用 ref.listen 收听值变化,然后将值设置为 SMIBool.

//...
late SMIBool _smile;
//...
_onInit(Artboard artboard) {
 this._artboard = artboard;
 _smile = controller.findInput<bool>('smile') as SMIBool;
}

@override
Widget build(BuildContext context) {
   ref.listen(signInLogoSmileProvider,
       (previous,  next) {
      // change value
      _smile.value = next;
   });

   return RiveAnimation.asset(
         riveFileName,
         artboard: 'board',
         onInit: _onInit,
       );
   }
}