I am using provider in my app, but I faced with unnecessary building.
Example
class AllWidget extends StatelessWidget{
@override
Widget build(BuildContext context){
print('state build called');
return ChangeNotifierProvider(
builder: (_) => MyCounter(),
child: Column(children: <Widget>[
MyCounterText(),
MyIncreaseButton(),
MyDecreaseButton(),
],
),
);
}
}
class MyCounterText extends StatelessWidget{
@override
Widget build(BuildContext context) {
final myCounter = Provider.of<MyCounter>(context, listen: false);
print('MyCounterText');
return Text(myCounter.num.toString());
}
}
class MyIncreaseButton extends StatelessWidget{
@override
Widget build(BuildContext context) {
final myCounter = Provider.of<MyCounter>(context, listen: false);
print('MyIncreaseButton');
return RaisedButton(
child: Text('Increase +'),
onPressed: ()=> myCounter.increment(),
);
}
}
class MyDecreaseButton extends StatelessWidget{
@override
Widget build(BuildContext context) {
final myCounter = Provider.of<MyCounter>(context, listen: false);
print('MyDecreaseButton');
return RaisedButton(
child: Text('Decrease -'),
onPressed: ()=> myCounter.decrement(),
);
}
}
Now if I click on MyIncreaseButton
widget, to inscrease the value, the MyDecreaseButton
widget builds too, even when I dont click on it.
And vice versa, if I click on MyDecreaseButton
widget, to descrease the value, the MyIncreaseButton
widget builds too, even when I dont click on it.
My Expectation is:
When clicking MyIncreaseButton
widget, MyDecreaseButton
widget should not build.
ShouldRebuild. A widget can prevent Child Widget unnecessary rebuilds. You can filter whether you need rebuild based on whether the property values received by the old Child Widget and the new Child Widget are equal.
One of the easiest ways to avoid unwanted reBuilds that are caused usually by calling setState() in order to update only a specific Widget and not refreshing the whole page, is to cut that part of your code and wrap it as an independent Widget in another Stateful class.
Example Using Provider So, first to get the String value created in the main. dart , all we have to do is call Provider. of<String>(context) , the of() method here will obtain the nearest Provider up its widget tree and returns its value.
the only reason why your widgets got rebuilds after keyboard pop up. is that one or more of your widgets size depends on MediaQuery. you can try to ge your screen size from LayoutBuilder as an alternative for MediaQuery.
There are multiple solutions:
context.read
or pass listen: false
to Provider.of
:RaisedButton(
onPressed: () {
context.read<MyModel>().increment();
// alternatively, do:
Provider.of<MyModel>(context, listen: false).increment();
},
child: Child(),
);
context.select
:Widget build(context) {
final increment = context.select((MyModel m) => m.increment);
return RaisedButton(
onPressed: increment,
child: Child(),
);
}
Selector
:Widget build(context) {
return Selector<MyModel, VoidCallback>(
selector: (_, model) => model.increment,
builder: (_, increment) {
return RaisedButton(
onPressed: increment,
child: Child(),
);
},
);
}
Selector is what you need. With selector you can filter updates. For example to update only when name change you can do something like this
Selector<AppStore, String>(
selector: (_, store) => store.name,
builder: (_, name, __) {
return Text(name);
},
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With