I use flutter riverpod for managing state. Function lightUpPlayTitle() is executed on tap with ref.read(titleBlurProvider.notifier).lightUpPlayTitle(), I can see in console it was from prints, but UI is updated only after hot reload. Why I must use hot reload to get UI updated? What mistake did I do?
full code
class StartPage extends StatelessWidget {
const StartPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Image.asset('assets/matches_background.jpeg'),
const TitlesWidget()
],
),
);
}
}
class TitlesWidget extends StatelessWidget {
const TitlesWidget({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TitleWidget(
text: 'Play',
index: 0,
callOnTap: () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: ((context) => const PositionedPage())));
},
),
TitleWidget(
text: 'Leads',
index: 1,
callOnTap: () {},
)
],
),
);
}
}
class TitleWidget extends ConsumerWidget {
TitleWidget(
{super.key,
required this.text,
required this.callOnTap,
required this.index});
String text;
Function callOnTap;
int index = 0;
@override
Widget build(BuildContext context, WidgetRef ref) {
final double opacity = ref.watch(titleBlurProvider)[index];
return Consumer(
builder: (context, ref, child) => Stack(
children: [
Opacity(
opacity: opacity,
child: ImageFiltered(
imageFilter: ImageFilter.blur(sigmaX: 3, sigmaY: 3),
child: Text(
text,
style: const TextStyle(
fontSize: 80,
fontWeight: FontWeight.bold,
color: Colors.white),
textAlign: TextAlign.center,
),
),
),
GestureDetector(
onLongPress: () => debugPrint(opacity.toString()),
onTap: () =>
ref.read(titleBlurProvider.notifier).lightUpPlayTitle(),
child: Opacity(
opacity: 0.8,
child: Text(
text,
style: const TextStyle(
fontSize: 80,
fontWeight: FontWeight.bold,
color: Colors.white),
textAlign: TextAlign.center,
),
),
),
],
),
);
}
}
final titleBlurProvider = StateNotifierProvider<TitleBlur, List<double>>(
(ref) => TitleBlur(),
);
class TitleBlur extends StateNotifier<List<double>> {
TitleBlur() : super([0, 0]);
startRegularBlur() {
Timer.periodic(const Duration(), (timer) {});
}
lightUpPlayTitle() {
debugPrint('light up');
while (state[0] < 1) {
Future.delayed(const Duration(milliseconds: 500));
state[0] = state[0] + 0.1;
if (state[0] > 1) state[0] = 1;
debugPrint(state[0].toString());
}
}
}
I tried moving Consumer to the top of widget tree but it didn't help me
You are mutating the list by changing the element in this line:
state[0] = state[0] + 0.1;
The state of a StateNotifier
should be immutable, so you have to clone the list and add the modification. You can do it like this:
state = [state[0] + 0.1, ...state.sublist(1)]
See about immutability of the state of StateNotifier
and how to modify the state here: https://riverpod.dev/docs/providers/state_notifier_provider
But please note that StateNotifier
is an old concept and is no longer recommended. The docs I linked above is in the "old" providers section. Please refer to the rest of Riverpod documentation for guides on the latest way to manage states using Riverpod.