Praveena
Praveena

Reputation: 6971

Is there any option for property wise notifyListerners in Provider?

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

Answers (1)

Alok Narasiman
Alok Narasiman

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

Related Questions