Есть ли какая-либо опция для мудрого свойства 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),
  ),
);

Это что-то вроде хака, поэтому я предлагаю рассмотреть более элегантные методы.

Другие вопросы по тегам