I’m currently working on a Flutter app using Riverpod, and I’ve encountered an issue with state management that I don’t understand. To debug, I simplified my code to this example, which you can run to follow along.
Here is the simplified code you can run it if you know about Riverpod Code Generation:
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'main.g.dart';
@riverpod
class RandomNumber extends _$RandomNumber {
@override
String build() {
print('im in build in quote provider');
return Random().nextInt(5).toString();
}
}
final giveBoolProvider = StateProvider<bool>((ref) => false);
void main() {
runApp(
ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final num = ref.watch(randomNumberProvider); // comment this
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Example')),
body: Center(
child: ElevatedButton(
onPressed: () {
ref.read(giveBoolProvider.notifier).update((state) {
return !state;
});
},
child: ref.watch(giveBoolProvider) == true
? Column(
mainAxisSize: MainAxisSize.min,
children: [Text(num), Text(num)], // comment this
// children: [Text(ref.watch(randomNumberProvider)), Text(ref.watch(randomNumberProvider))], // uncomment this
)
: const Text('giveBool is false'),
),
),
));
}
}
Problem:
When I press the button, a random number is shown. If I press the button again, nothing happens. Pressing the button a third time shows the same random number because the state of randomNumberProvider
did not change. This is the expected behavior.
However, when I:
Comment out the lines marked with // comment this.
Uncomment the lines marked with // uncomment this.
The build method of randomNumberProvider
is called every time, even though I haven’t explicitly changed its state. This results in a new random number being generated each time the button is pressed.
In both scenarios, the widget’s build method is called. I’m unsure why the state behaves differently in these two cases.
Could someone explain what I’m missing here and why there’s a difference in behavior between the two scenarios?
Thank you!