Есть ли какая-либо опция для мудрого свойства notifyListerners в Provider?
Я работаю над списком дел, используя пакет провайдера для управления состоянием. На экране создания задачи у меня есть виджеты, как
- Название задачи
- Тип дела
- Выбор цвета задачи
- Дата и время
- Кнопка Сохранить
Модель задачи
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();
}
}
Я использую ChangeNotificationprovider
нравится
ChangeNotifierProvider<Task>.value(
value: Task(),
child: Consumer<Task>(
builder: (context, task, _) {
return Scaffold(...
...
NameWidget(),
ColorWidget(),
TypeWidget(),
.....
Таким образом, каждый виджет будет изменять соответствующие поля модели Задачи, но проблема, с которой я сталкиваюсь, заключается в том, что когда виджет обновляет поле модели задачи, все виджеты в Consumer
обновляется, как всякий раз, когда я обновляю color
Приложение field обновит не только поле цвета, но и все остальные поля. Есть ли другой способ разработки архитектуры этого провайдера, например, отправка уведомлений только определенным слушателям поля?
Это то, что я пытался.
Вместо того чтобы делать Task
ChangeNotifier
Я пытался создать каждое поле как отдельный класс и ChangeNotifier. Например, name
поля становятся такими
class Task {
Name _name;
}
class Name with ChangeNotifier {
String _name;
}
Но это, кажется, слишком много стандартного кода.
1 ответ
Это не самое элегантное решение, но работает
Сначала создайте класс, который принимает переменную динамического типа, которая расширяет changeNotifier.
class NotifiedVariable<T> with ChangeNotifier {
T _value;
NotifiedVariable(this._value);
T get value => _value;
set value(T value) {
_value = value;
notifyListeners();
}
}
Теперь вы можете установить тип всех ваших переменных к этому
class c {
NotifiedVariable<int> integer;
NotifiedVariable<string> stringVal;
c(int integer, string stringVal) {
this.integer = NotifiedVariable<int>(integer);
this.stringVal = NotifiedVariable<string>(stringVal);
}
}
Теперь вы можете внедрить этот класс, я использую get_it и получаю значение в другом месте. Используйте провайдера для значения непосредственно выше, где это необходимо. Это может все еще не работать, если многократные значения необходимы. Я предлагаю создать другой класс и наследовать необходимые значения от класса c.
ChangeNotifierProvider<T>.value(
value: locator.get<c>().integer,
child: Consumer<T>(
builder: (context, NotifiedVariable variable, child) => Widget(v: variable.value),
),
);
Это что-то вроде хака, поэтому я предлагаю рассмотреть более элегантные методы.