Ijk
Ijk

Reputation: 35

Using riverpod to maintain a global Map<String, int> in flutter

I have implemented a provider using the new syntax based on the example of counter in the riverpod documentation.

Riverpod Example:

@riverpod
class CounterNotifier extends $CounterNotifier {
@override
int build() = 0;
void increment() = state++;
void decrement() = state++;
}

My provider:

@riverpod
class ViewsCounterNotifier extends _$ViewsCounterNotifier {
@override
Map<String, int> build() {
return {};
} 
void add(String id) {
if (state.containsKey(id)) {
state[id] = state[id]! + 1;
} else {
state[id] = 1;
print(state);
}
}
}

Im able to read and update the map first time using ref.read(viewsCounterNotifierProvider.notifier).add(widget.product.id!);

but any subseequent read leads to re-initialization of provider because of

@override
Map<String, int> build() {
return {};
} 

and previous data is lost. How to maintain the data.

Upvotes: 0

Views: 233

Answers (1)

Dhafin Rayhan
Dhafin Rayhan

Reputation: 8529

Generated providers have an auto-disposing behavior by default. If there are no listeners to the provider, the state will reset. To disable auto dispose, specify keepAlive: true in the annotation. Change @riverpod to:

@Riverpod(keepAlive: true)

Another problem in your code is the use of mutable state in the provider. In short, you should not mutate the state object and expect the provider to notice the state update. A minimal change to make the add method works is to have a copied state before reassigning it to the notifier state:

@riverpod
class ViewsCounterNotifier extends _$ViewsCounterNotifier {
  @override
  Map<String, int> build() {
    return {};
  }

  void add(String id) {
    final copiedState = {...state}; // Copy the state to a local variable

    // Make mutations to the local map object
    if (copiedState.containsKey(id)) {
      copiedState[id] = copiedState[id]! + 1;
    } else {
      copiedState[id] = 1;
    }

    // Reassign the state with the modified local map object
    state = copiedState;
  }
}

A better approach might be to use control-flow operators.

Upvotes: 2

Related Questions