I created two widgets from same custom StatefulWidget
class. I want them to use separate ChangeNotifier
instance from same ChangeNotifier
derived class because they need to consume different data set. Unfortunately just like below example, it's not working like I want it to. Both read()
and watch()
respectively write and read data on the same ChangeNotifier
instance.
Wait a minute. Isn't that what Provider
supposed to do?. Yes I know. I'm aware that. But now I just need a little flexibility. I think I'm just using Provider
the wrong way if I'm not wrong.
Thank you for your help. Greatly appreciate it.
MultiProvider App() => MultiProvider(
...
providers : [
...
ChangeNotifierProvider(create : (_) => Notifier()),
]
);
class TestState extends State<Test>{
GlobalKey<CounterState> gk1 = GlobalKey<CounterState>();
GlobalKey<CounterState> gk2 = GlobalKey<CounterState>();
@override
Widget build(BuildContext context){
...
.. [Counter(gk1), Counter(gk2)]
...
.. onPressed: (){
.. gk1.currentState?.increment(1);
.. gk2.currentState?.increment(2);
.. },
...
}
}
class CounterState extends State<Counter>{
@override
Widget build(BuildContext context){
...
.. context.watch<Notifier>().count
...
}
void increment(int v){
context.read<Notifier>().count = v;
}
}
class Notifier with ChangeNotifier{
int _count = 0;
int get count => _count;
void set count(int v){
_count = v;
notifyListeners();
}
}
CodePudding user response:
I remember facing this exact issue when I was using this package. I did a little search but couldn't find much info about it, so I decided to change approach.
Instead of having N providers of the same type, I now create 1 provider containing all the info for the N widgets.
In your case I would do something like:
class Notifier with ChangeNotifier{
List<int> _counts = [0, 0];
int getCountAt(int index) {
return _counts[index]; //Control list lenght of course
}
void set count(int index, int v){
_count[index] = v;
notifyListeners();
}
}
Relying on index to access the correct counter might not work. If that's the case, you can create a more complex object to access it's counter (maybe an id? a UniqueKey?).
CodePudding user response:
I guess there's no other way yet to solve this problem easily. Either I was missing something or Provider
doesn't yet support binding with ChangeNotifier
by any passed instance directly not by only a single instance of the class. So I marked Axel's as the answer for now.
But based on the example in the question, for my case I use state instance for the key to identify the different data set, and binding it with a "change notifier instance" exactly.
class CounterState extends State<Counter>{
@override
Widget build(BuildContext context){
...
.. context.watch<Notifier>().instance(this).count
...
}
void increment(int v){
context.read<Notifier>().instance(this).count = v;
}
}
class Notifier with ChangeNotifier{
Map<State, NotifierInstance> _instance = {};
NotifierInstance instance(State state){
if(_instance[state] == null) _instance[state] = NotifierInstance(this);
return _instance[state]!;
}
}
class NotifierInstance{
Notifier notifier;
int _count = 0;
NotifierInstance(this.notifier);
int get count => _count;
void set count(int v){
_count = v;
notifier.notifyListeners();
}
}