Nicolas Morawietz
Nicolas Morawietz

Reputation: 108

Clean solution for Rive and Riverpod

In my flutter app I want to use Rive for animations and Riverpod for state management. So now I'm looking for a performant way to listen to the state of my provider to manage the state of my SMIInput<bool>. Currently I wrap the Rive widget with a consumer, to get the state from riverpod and set the controllers value.

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

I suppose that this runs the build method of the Rive widget once _smile.value is set and once it returns the widget.

- Am i getting this right?

For that purpos i tried calling addListener to the providers notifier to set _smile.value there.

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

But this runs just one time and not on every state change as I hoped it does.

- Are there other suggestions for altering the controllers input values without need to use 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);
});

I need to watch signInFormProviders state instead of signInFormProvider.notifiers state for the same reason addListeners only runs one time.

- Is this bad practice, or am I doing something wrong here?

If you had any nice implementations of Rive and Riverpod hand in hand, I would appreciate that.

Upvotes: 1

Views: 590

Answers (1)

Dario Digregorio
Dario Digregorio

Reputation: 462

I am using a newer version of Riverpod and Rive, but you could do it easily by using a ConsumerStatefulWidget and then listening to the value changes with ref.listen and then setting the value to 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,
       );
   }
}

Upvotes: 2

Related Questions