Reputation: 6971
I am working on a to-do list app using provider package for state management. In task creation screen I have widgets like
Task model
class Task with ChangeNotifier {
String _name;
String _type;
Color _color;
String get name => _name;
set name(String name) {
_name = name;
notifyListeners();
}
Color get color => _color;
set color(Color color) {
_color = color;
notifyListeners();
}
String get type => _type;
set type(String type) {
_type = type;
notifyListeners();
}
}
I am using ChangeNotificationprovider
like this
ChangeNotifierProvider<Task>.value(
value: Task(),
child: Consumer<Task>(
builder: (context, task, _) {
return Scaffold(...
...
NameWidget(),
ColorWidget(),
TypeWidget(),
.....
So each widget will be changing respective fields of the Task model but the problem I am facing is whenever a widget updates a field of the task model all the widgets under Consumer
is getting updated, like whenever I update color
field app will refresh not an only color field but all other fields. Is there any other way to design this provider architecture like sending notification only to specific field listeners?
This is what I tried.
Instead of making Task
a ChangeNotifier
I tried to create each field as a separte class and ChangeNotifier. For example, name
fields become like this
class Task {
Name _name;
}
class Name with ChangeNotifier {
String _name;
}
But this seems to be too much boilerplate code.
Upvotes: 2
Views: 687
Reputation: 144
This is not the most elegant solution but works
First create a class which accepts a dynamic type variable that extends changeNotifier.
class NotifiedVariable<T> with ChangeNotifier {
T _value;
NotifiedVariable(this._value);
T get value => _value;
set value(T value) {
_value = value;
notifyListeners();
}
}
You can now set the type of all your variables to this
class c {
NotifiedVariable<int> integer;
NotifiedVariable<string> stringVal;
c(int integer, string stringVal) {
this.integer = NotifiedVariable<int>(integer);
this.stringVal = NotifiedVariable<string>(stringVal);
}
}
Now you can inject this class, I use get_it and obtain the value elsewhere. Use provider for the value directly above where its needed. This may still not work if multiple values are needed. I suggest making another class and it to inherit the necessary values from class c.
ChangeNotifierProvider<T>.value(
value: locator.get<c>().integer,
child: Consumer<T>(
builder: (context, NotifiedVariable variable, child) => Widget(v: variable.value),
),
);
This is kind of a hack so I suggest looking into more elegant methods.
Upvotes: 1