Reputation: 35
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
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