import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(const MyApp());
}
class Counter1 extends ChangeNotifier {
int _counter = 0;
int get counter {
return _counter;
}
void increment() {
_counter = _counter + 1;
notifyListeners();
}
void reset() {
_counter = 0;
notifyListeners();
}
}
class Counter2 extends ChangeNotifier {
int _counter = 0;
int get counter {
return _counter;
}
void increment() {
_counter = _counter + 1;
notifyListeners();
}
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: MultiProvider(providers: [
ChangeNotifierProvider(
create: (context) {
return Counter2();
},
),
ChangeNotifierProxyProvider<Counter2, Counter1>(
create: (context) {
return Counter1();
},
update: (BuildContext context, Counter2 value, Counter1? previous) {
if (previous == null) {
throw StateError("Counter1 is null");
}
value.removeListener(previous.reset); // To avoid multiple listener
value.addListener(previous.reset);
return previous;
},
),
], child: const MyHomePage()),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
var counter1 = Provider.of<Counter1>(context);
var counter2 = Provider.of<Counter2>(context);
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title:
const Text("Let's try to reset counter 1 when counter 2 increment"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Counter 1:',
),
Text(
'${counter1.counter}',
style: Theme.of(context).textTheme.headlineMedium,
),
ElevatedButton(
onPressed: counter1.increment,
child: const Text("Increment counter 1")),
const Text(
'Counter 2:',
),
Text(
'${counter2.counter}',
style: Theme.of(context).textTheme.headlineMedium,
),
ElevatedButton(
onPressed: counter2.increment,
child: const Text("Increment counter 2")),
],
),
),
);
}
}
2
Answers
To simplify the code, you can remove the manual adding and removing of listeners by using context.watch, which automatically listens for changes.
Here is my proposition:
Your use of ChangeNotifierProxyProvider is generally correct, but there’s a small issue in how you’re managing the listeners. Let’s modify the code to fix this and improve the overall structure. Here’s the full, corrected version of your code:
Key changes and improvements:
This implementation should work as intended: Counter1 will reset to 0 whenever Counter2 is incremented. The use of ChangeNotifierProxyProvider is correct here, as it allows Counter1 to depend on and react to changes in Counter2.