How to avoid unnecessary rebuilds while using provider in flutter? How to avoid unnecessary rebuilds while using provider in flutter? dart dart

How to avoid unnecessary rebuilds while using provider in flutter?


There are multiple solutions:

  • use 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(),);
  • use context.select:
Widget build(context) {  final increment = context.select((MyModel m) => m.increment);  return RaisedButton(    onPressed: increment,    child: Child(),  ); }
  • use 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);  },);


I just avoided unnecessary rendering by editing my code as the following:

import 'package:flutter/material.dart';import 'package:provider/provider.dart';import 'package:flutter/foundation.dart';class MyCounter with ChangeNotifier {  int _num = 0;  int get num => _num;  set num(int n) {    _num = n;    notifyListeners();  }  void increaent() {    _num = _num + 1;    notifyListeners();  }  void decrement() {    _num = _num - 1;    notifyListeners();  }}void main() {  runApp(MyApp());}class MyApp extends StatelessWidget {  @override  Widget build(BuildContext context) {    print('root build called');    return ChangeNotifierProvider(        builder: (context) => MyCounter(),        child: MaterialApp(          title: 'MyAppJan',          home: Scaffold(            appBar: AppBar(title: Text('Home')),            body: AllWidget(),          ),          theme: ThemeData(primarySwatch: Colors.orange),        ));  }}class AllWidget extends StatelessWidget {  @override  Widget build(BuildContext context) {    print('state build called');    return Center(      child: Column(        children: <Widget>[          MyCounterText(),          SizedBox(height: 10),          MyIncreaseButton(),          SizedBox(height: 10),          MyDecreaseButton(),        ],        mainAxisAlignment: MainAxisAlignment.center,        mainAxisSize: MainAxisSize.min,      ),    );  }}class MyCounterText extends StatelessWidget {  @override  Widget build(BuildContext context) {    print('MyCounterText');    return Consumer<MyCounter>(      builder: (context, myCounter, _) {        return Text(myCounter.num.toString());      },    );  }}class MyIncreaseButton extends StatelessWidget {  @override  Widget build(BuildContext context) {    final _items = Provider.of<MyCounter>(context,listen: false);    print('MyIncreaseButton');    return RaisedButton(      child: Text('Increase ++'),      onPressed: () => _items.increment(),    );  }}class MyDecreaseButton extends StatelessWidget {  @override  Widget build(BuildContext context) {    final _items = Provider.of<MyCounter>(context,listen: false);    print('MyDecreaseButton');    return RaisedButton(      child: Text('Decrease --'),      onPressed: () => _items.decrement(),    );  }}