How to avoid unnecessary rebuilds while using provider in flutter?
There are multiple solutions:
- use
context.read
or passlisten: false
toProvider.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(), ); }, );}
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(), ); }}