Flutter Provider-with Selector

Sriram
3 min readAug 28, 2019

--

This is my second article on Flutter — provider. Check the link below for the first article.

But why again on the provider?

Let me explain this with a simple problem with a simple example.

let us imagine we had a counter application, but this time with two buttons and two text fields. Most of our problems are solved by the consumer. But now, I will introduce you to the problem with the consumer.

Now let the first text field(tf1) value is being displayed using consumer and the same with tf2. Let the two floating action buttons be fab1 and fab2.

Here tf1 and tf2 are initialized with 0 value and clicking on fab1 increments the value in tf1 and fab2 decrements the value in tf2.

Problem: On clicking on fab1

Consumer<CounterProvider>(builder: (context, data,child) {print("object123");return Text('${data.getCount}');},)
Consumer<CounterProvider>(
builder: (context, data,child) {print("object123");return Text('${data.getCount1}');},)

As we are using notifyListeners(), every consumer of that particular Provider will be notified. Here, It forces the second consumer to rebuild its child(which is not necessary).

It would be okay with small scale applications, but if you are dealing with some complex operations, to be triggered on the change of a certain flag, believe me, it will be a serious bug.

Here comes the Selector to let you gain the control over your code

The selector was introduced to the Provider package on Aug 20, 2019, in v3.1.0. what does a selector do?

Let me get you to the code first before getting you confused.

Selector<CounterProvider,int>(builder: (context, data,child) {print("object");return Text('$data');}, selector: (buildContext , countPro)=>countPro.getCount,),

Step1: Replace Consumer with Selector.

Selector<CounterProvider, int>, here CounterProvider is the ChangeNotifier Class, and int is the type of data we are observing.

Step2: Implement selector.

In selector, we would have two parameters one is buildcontext and the other is the object of the provider.

Step3: Return the data

Return the particular data you want to rebuild the child on its change.

Explanation: here the data in the builder resembles the value of counter.getCount, which you are returning in the selector, alone .No need to use data.getCount to display the value

Selector<CounterProvider,int>(builder: (context, data,child) {print("object");return Text('$data');}, selector: (buildContext , countPro)=>countPro.getCount,),Selector<CounterProvider,int>(builder: (context, data,child) {print("object123");return Text('$data');}, selector: (buildContext , counterProvider ) =>counterProvider.getCount1,)

The Selector, from the above code, solves our problem by rebuilding the child only when there is a change in the value of the particular value the selector is returning.

Here is the complete code

---------main.dart
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MultiProvider(providers:[ChangeNotifierProvider(builder: (BuildContext context) =>CounterProvider(),),],child: MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.teal,),home:Counter()),);}}////////////
-------Counter.dartimport 'package:flutter/material.dart';import 'package:provider/provider.dart';import 'counter_provider.dart';class Counter extends StatefulWidget {
@override
_CounterState createState() => _CounterState();}class _CounterState extends State<Counter> {
@override
Widget build(BuildContext context) {final counterProvider=Provider.of<CounterProvider>(context,listen: false);return SafeArea(child: Scaffold(body: Center(child:Column(children: <Widget>[Selector<CounterProvider,int>(builder: (context, data,child) {print("object");return Text('$data');}, selector: (buildContext , countPro)=>countPro.getCount,),Selector<CounterProvider,int>(builder: (context, data,child) {
print("object123");
return Text('$data');
},
selector:
(buildContext , counterProvider)=>counterProvider.getCount1,
)],)),floatingActionButton: Row(children: <Widget>[FloatingActionButton(onPressed: () {counterProvider.incrementCounter();},),FloatingActionButton(onPressed: () {counterProvider.incrementCounter1();},),],), ),);}}/////////////-----counter_provider.dartimport 'package:flutter/foundation.dart';import 'package:provider/provider.dart';class CounterProvider extends ChangeNotifier{int count =0;
int count1 =0;
int get getCount1=>count1;int get getCount=>count;incrementCounter(){count++;notifyListeners();}incrementCounter1(){count1--;notifyListeners();}}

I hope you got this.

--

--