# Provider



With Providers and MultiProviders we can do easy StateManagement in Flutter.![](https://miro.medium.com/max/60/1*e9u8i0Ltil2MDKp8j-Sd_w.png?q=20)![](https://miro.medium.com/max/3840/1*e9u8i0Ltil2MDKp8j-Sd_w.png)State Management in Flutter using Provider

## **Watch Youtube Tutorial** <a href="#id-49d7" id="id-49d7"></a>

State Management In Flutter made Easy

## **Add Dependencies First** <a href="#id-1ec5" id="id-1ec5"></a>

Go to your _**pubspec.yaml**_ file add the below dependency,

I would recommend to add the latest dependency version, at this moment it is 4.0.4

```
provider: ^4.0.4
```

_The Providers will have_

1. _**ChangeNotifiers**_
2. _**ChangeNotifierProviders**_
3. _**Consumers**_

The Basic flow to update a state in Provider is to call notifyListeners() on the Listener class which in turn calls the Change Notifier and then the corresponding model Consumer widget will be triggered with the Model Data.

_**So Don’t get confused, it’s really easy. Let’s see how that works.**_

So we have two screens here\
1\. **Home Screen**\
**2. Add Items Screen**

## **Aim:** <a href="#b78f" id="b78f"></a>

_We will be creating a Shopping List here and the user should be able to add data to the Shopping list from anywhere in the Flutter Application._

The Add Items Screen will have a Textfield and a button. When the user hits the button, he/she should be able to add data from the Add Item screen to the Home Screen and update the Shopping List in the Home Screen.

This can be achieved with the help of Providers.

First thing I need is a Notifier class for each of my DataModel.

Our model is called ‘Item’

```
class Item {
  String itemName;
  Item(this.itemName);
}
```

We also need a Notifier class named “ItemAddNotifier” which will look like this

```
import 'package:flutter/material.dart';
import 'Item.dart';class ItemAddNotifier extends ChangeNotifier {
  //
  List<Item> itemList = [];addItem(String itemName) async {
    Item item = Item(itemName);
    itemList.add(item);    notifyListeners();
  }
}
```

So this is an individual class and we have not linked it to anything yet.

In the above class, you can see that it has extended ‘ChangeNotifier’ which means whenever there is some trigger for this model from anywhere in the application for the model ‘ItemAddNotifier’, this class will be triggered.

Let’ check this in the AddItemScreen class below

_Create a new File named AddItemScreen.dart_

Here is the build method for this screen.

We are opening this screen from the Home Screen, and the Add Item button on this screen will close this screen and return to HomeScreen.

```
 TextField(
    controller: _itemNameController,
    decoration: InputDecoration(
      contentPadding: EdgeInsets.all(15.0),
      hintText: 'Item Name',
    ),
  ),
  SizedBox(
    height: 20.0,
  ),
  RaisedButton(
    child: Text('ADD ITEM'),
    onPressed: () async {
      if (_itemNameController.text.isEmpty) {
        return;
      }
      await Provider.of<ItemAddNotifier>(context, listen: false)
          .addItem(_itemNameController.text);
      Navigator.pop(context);
    },
  )
```

![](https://miro.medium.com/max/60/1*vTxx4JDyx7jtYvPbca9DdQ.png?q=20)![](https://miro.medium.com/max/497/1*vTxx4JDyx7jtYvPbca9DdQ.png)Add Item Screen

Here you can see we are calling

```
Provider.of<ItemAddNotifier>(context)
 .addItem(_itemNameController.text);
```

_\_itemNameController_ is the controller for the TextField.

This code will trigger the ‘_ItemAddNotifier_’ class and then you will have access to all the methods inside ‘ItemAddNotifier’ class. As you can see the above code the ‘addItem’ method is being called which calls the ‘addItem’ method in the ‘ItemAddNotifier’ class and add it to the data to the itemList in the class and then we are calling the important method ‘notifyListeners()’ which notifiers the ChangeNotifier that we have not written yet. Let’s write that.

So here we want to use the ItemAddNotifier across the application, not only for the HomeScreen.

For this reason, we need to add the ChangeNotifierProvider to the root of the Application.

Let’s go to the _**main.dart**_ file which is the entry point of your Flutter Application.

So here the main.dart file will look like this.

```
import 'package:flutter/material.dart';
import 'package:flutter_demos/Provider/ItemAddNotifier.dart';
import 'package:flutter_demos/Provider/ShopNameNotifier.dart';
import 'package:provider/provider.dart';
import 'Provider/HomeScreen.dart';void main() {
  runApp(HomeApp());
}class HomeApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<ItemAddNotifier>(
      create: (BuildContext context) {
        return ItemAddNotifier();
      },
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        home: HomeScreen(),
      ),
    );
  }
}
```

In the above code, we are wrapping the whole Root Widget which is the **MaterialApp** widget inside the ‘_ChangeNotifier_’ widget. This makes sure that the whole application receives the updates whenever there is a change in the Shopping List.

Now it’s time to receive the Data anywhere in the application. In this example, we will consume it in the HomeScreen. The ‘_Consumer_’ widget with the correct ‘Notifier Class’ consumes the corresponding data. Here our Notifier is ‘_ItemAddNotifier_’

**HomeScreen**

```
import 'package:flutter/material.dart';
import 'package:flutter_demos/Provider/AddItemScreen.dart';
import 'package:flutter_demos/Provider/ItemAddNotifier.dart';
import 'package:flutter_demos/Provider/ShopNameNotifier.dart';
import 'package:provider/provider.dart';class HomeScreen extends StatelessWidget {
  //
  HomeScreen() : super();final String title = 'Home';@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.add),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  fullscreenDialog: true,
                  builder: (context) {
                    return AddItemsScreen();
                  },
                ),
              );
            },
          )
        ],
      ),
      body: Container(
        padding: EdgeInsets.all(30.0),
        child: Column(
          children: <Widget>[
            Expanded(
              child: Consumer<ItemAddNotifier>(
                builder: (context, itemAddNotifier, _) {
                  return ListView.builder(
                    itemCount: itemAddNotifier.itemList.length,
                    itemBuilder: (context, index) {
                      return Padding(
                        padding: EdgeInsets.all(15.0),
                        child: Text(
                          itemAddNotifier.itemList[index].itemName,
                          style: TextStyle(
                            fontSize: 20.0,
                            color: Colors.black,
                          ),
                        ),
                      );
                    },
                  );
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}
```

In the above code you can see the ‘Consumer’ widget

```
Consumer<ItemAddNotifier>(
                builder: (context, itemAddNotifier, _) {
```

Here the second parameter is our Notifier. From the parameter you can access all the members in the Notifier class.

```
itemAddNotifier.itemList // like this
```

And That’s it.

**Advantages**

1. Whenever there is change in data for this Model, only the Consumer widget corresponding to that Model will be rebuilt results in improved Performance.
2. You can have any number of Consumers and update anywhere from the application, and use less setState().

## **What if I have More Notifiers?** <a href="#c639" id="c639"></a>

This is absolutely possible that you will have more than one data model and corresponding notifiers, in that case you can use ‘MultiProviders’.

Let’s say I have a ShopNameNotifier which looks something like this

```
import 'package:flutter/material.dart';class ShopNameNotifier extends ChangeNotifier {
  //
  String shopName = '';updateShopName(String shopName) async {
    this.shopName = shopName;
    notifyListeners();
  }
}
```

So to add the Change Notifier, we will update the _**main.dart**_ like this

```
import 'package:flutter/material.dart';
import 'package:flutter_demos/Provider/ItemAddNotifier.dart';
import 'package:flutter_demos/Provider/ShopNameNotifier.dart';
import 'package:provider/provider.dart';
import 'Provider/HomeScreen.dart';void main() {
  runApp(HomeApp());
}class HomeApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider<ItemAddNotifier>(
          create: (BuildContext context) {
            return ItemAddNotifier();
          },
        ),
        ChangeNotifierProvider<ShopNameNotifier>(
          create: (BuildContext context) {
            return ShopNameNotifier();
          },
        )
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        home: HomeScreen(),
      ),
    );
  }
}
```

Here you can see we added the ‘MultiProvider’ widget with two ‘ChangeNotifierProvider’ with two models.

To Update the ShopName, call like below from any class.

```
Provider.of<ShopNameNotifier>(context)
    .updateShopName('Shop One');
```

And to Consume the data is simple,

```
Consumer<ShopNameNotifier>(
  builder: (context, shopNameNotifier, _) {
    return Text('Shop Name: ${shopNameNotifier.shopName}');
  },
),
```

Thats it!!!

Done, So you can see we are using setState() nowhere in the application.![](https://miro.medium.com/max/28/1*2sHMENxAbNuVc2xXGY5s_w.png?q=20)![](https://miro.medium.com/max/500/1*2sHMENxAbNuVc2xXGY5s_w.png)Shopping List Screen

## **Complete Source Code** <a href="#id-352e" id="id-352e"></a>

[https://bitbucket.org/vipinvijayan1987/tutorialprojects/src/ProviderDemo/FlutterTutorialProjects/flutter\_demos/](https://bitbucket.org/vipinvijayan1987/tutorialprojects/src/ProviderDemo/FlutterTutorialProjects/flutter_demos/)[Vipin Vijayan](https://medium.com/vipin-vijayan?source=post_sidebar--------------------------post_sidebar-)



*
