flutterriverpodrive

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.


Solution

  • 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,
           );
       }
    }