Provider: Watch or Read
Part of the State Management section of Coddy's Flutter journey. Lesson 11 of 27.
There are two ways to get a model from Provider, and they do different jobs.
context.watch<StepCounter>() gets the model and subscribes to it: when the model calls notifyListeners(), this widget builds again. Use it in build, for anything the screen shows.
context.read<StepCounter>() gets the model once, with no subscription. Use it in callbacks such as onPressed, where you want to call a method and not to show anything:
Widget build(BuildContext context) {
final steps = context.watch<StepCounter>().steps; // shows
return ElevatedButton(
onPressed: () => context.read<StepCounter>().walk(), // acts
child: Text('$steps steps'),
);
}Mix them up and you see it. read in build shows the first value forever. watch inside onPressed is an error, because a tap is not a build and there is nothing to subscribe.
Challenge
EasyWalk adds 1000 steps to the model, but the screen stays at 0 steps.
- Make the steps line follow the model, so each tap shows the new number.
- Keep the button's call as it is.
Try it yourself
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class StepCounter extends ChangeNotifier {
int _steps = 0;
int get steps => _steps;
void walk() {
_steps += 1000;
notifyListeners();
}
}
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => StepCounter(),
child: const MyApp(),
),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
@override
Widget build(BuildContext context) {
final steps = context.read<StepCounter>().steps;
return Scaffold(
appBar: AppBar(title: const Text('Steps')),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('$steps steps', style: const TextStyle(fontSize: 40)),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
context.read<StepCounter>().walk();
},
child: const Text('Walk'),
),
],
),
),
);
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in State Management
Practice on your own: Online Flutter compiler