StateProvider gets updated but ref.listen does not triggers

183 Views Asked by At

I have a StateProvider defined in a file (separated from any class) as follow :

final XYProvider = StateProvider<List<double>>((ref) ( return [0.0,0.0])); 

it gets updated like this (for the most part) :

ref.read(XYPosProvider.notifier).state[0] =

            (ref.read(currentXPosProvider.notifier).state -

                        ref.read(initialXPosProvider.notifier).state) *

                    80000 +

                39;

And in another file I want to call a method when the value is updated using

ref.listen() : 
void userPositionNodesMaker(List<double>? XYPos) {

      bool isInBoundaries(var _) {

        return _ > 0 && _ < (iMazeLength - 1);

      }



      setState(() {

        print(XYPos![0].round());

        print(XYPos[1].round());



        if (isInBoundaries(XYPos[0].round()) &&

            isInBoundaries(XYPos[1].round())) {

          mazeMatrix[XYPos[0].round()][XYPos[1].round()].setUserNode();

        }

      });

    }



    ref.listen(XYPosProvider, (List<double>? prev, List<double>? next) {

      print('XYPOSCHANGED');

      userPositionNodesMaker(next);

    });  

This is placed in the Widget build of this ConsumerStatefulWidget and I dont under stand why it does not triggers. I have a button inside this Widget printing the value of XYPosProvider showing that it is well updated and acessed in my widget but still nothing happens in the ref.listen

Tried Notification but I did not have sucess trying to create a custom one instead of ScrollNotifications. Im looking on ChnageNotifier as an alternative for the moment but still I can’t figure out why ref.listen wouldn’t work.

2

There are 2 best solutions below

1
Ruble On

Your problem is that you have to change the state of collections in an immutable way. For example, it goes like this:

final newState = ref.read(XYPosProvider.notifier).state;

newState = newState[0] = 
  ref.read(currentXPosProvider.notifier).state -
  (ref.read(initialXPosProvider.notifier).state * 80000 + 39);


// update state:
ref.read(XYPosProvider.notifier).state = [...newState];
// or 
ref.read(XYPosProvider.notifier).state = List.of(newState);

1
Léandre Raeth On

As suggested I switched to StateNotifierProvider and it works just fine Here what I modified :

``` class XYPosNotifier extends StateNotifier<List<double>> {
  XYPosNotifier() : super([39, 20]);

  void updatePosition(double x, double y) {
    state = [x, y];
  }
}

final xyPosProvider = StateNotifierProvider<XYPosNotifier, List<double>> 
 ((ref) {
  return XYPosNotifier();
}); 

bit more heavy but really usefull even when updating it looks like this now : ref.read(xyPosProvider.notifier).updatePosition(x, y);