Flutter Riverpod - Part 2
Tags: flutter, android, ios, webdev
Published: 2022-03-21 06:19:53

In the last [blog](https://chandramcodes.hashnode.dev/hello-flutter-with-riverpod-100/), we learned to set up Riverpod for a Flutter Project and how to use the basic of all Riverpod Provider, the `Provider()`. In this blog we will learn to use the most useful and basic Provider, the `StateProvider()`.

## Let's dig into why do we need a Provider?

Let's say you have an A Flutter(Riverpod) Project with the following code
```
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

int counter = 0;

void main() {
  runApp(
    const ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Riverpod',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Riverpod'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$counter',
              style: Theme.of(context).textTheme.headline4,
            ),
            const CounterCard()
          ],
        ),
      ),
    );
  }
}

class CounterCard extends StatefulWidget {
  const CounterCard({
    Key? key,
  }) : super(key: key);

  @override
  State<CounterCard> createState() => _CounterCardState();
}

class _CounterCardState extends State<CounterCard> {
  void _incrementCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Card(
        child: ListTile(
      title: Text("$counter"),
      trailing: IconButton(
        icon: const Icon(Icons.plus_one),
        onPressed: _incrementCounter,
      ),
    ));
  }
}


```
Whats all this Provider Scope? Read my [previous blog](https://chandramcodes.hashnode.dev/hello-flutter-with-riverpod-100) on setting up Riverpod for your Project!

So what's going on in the code above?
Its the similar Default Flutter Counter Application that we get when we create a new Flutter Project, but with Riverpod and some Changes to display the problem with state. 
We have a global variable `int counter` which is initialised to Zero. Then that `counter` is used at two places, one in the upper `MyHomePage` Class and second in `CounterCard` Class. In the `CounterCard`, there's an `IconButton` with the function `_incrementCounter()` which increments the `counter` variable. Now Ideally, on pressing the button, we should see the `counter` getting incremented at both the places. But this doesn't happen. This is because the `setState()` method only refreshes the `CounterCard` Contents and not of `MyHomePage`. Flutter State works in this way to improve performance, imagine the entire screen refreshing everytime for small changes and you don't own an M1 Device. To solve this problem we have State Management Solutions. Let's figure it all out using some diagrams!! Who doesn't love diagrams right?

![Instagram post - 1.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1647773435190/x5AEi9TdI.png)
![Instagram post - 2.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1647773427447/gCe0I0B-Y.png)

So if you want to change the state of a base class from a derived class(which happens quite frequently), it becomes quite tedious, we are gonna solve this problem with Riverpod, more specifically with a `Provider` that contains state or `StateProvider()`.

So we have a `counter` variable right? We are going to convert it into `Provider` just how we learned in the [previous blog](https://chandramcodes.hashnode.dev/hello-flutter-with-riverpod-100).

```
//int counter = 0; This Changes to
final counterProvider = Provider<int>((ref) {
  return 0;
});
```
And half the Magic is Done!!

Change the `MyHomePage` to a Stateless Widget...
```
class MyHomePage extends StatelessWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$counter',
              style: Theme.of(context).textTheme.headline4,
            ),
            const CounterCard()
          ],
        ),
      ),
    );
  }
}
```
Again cahnge the `MyHomePage` to a `ConsumerWidget` just like we learned in the [previous blog](https://chandramcodes.hashnode.dev/hello-flutter-with-riverpod-100) and let the `Text` Widget watch the `counterProvider()`
```

class MyHomePage extends ConsumerWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  Widget build(BuildContext context,WidgetRef ref) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              ref.watch(counterProvider).toString(),
              style: Theme.of(context).textTheme.headline4,
            ),
            const CounterCard()
          ],
        ),
      ),
    );
  }
}
```
Now sometimes you need to read a provider from a `StatefulWidget`, and we do this using `ConsumerStatefulWidget` which we will do to the `CounterCard` StatefulWidget.
```
// Add Consumer to StatefulWidget
class CounterCard extends ConsumerStatefulWidget {
  const CounterCard({
    Key? key,
  }) : super(key: key);

  @override
//    Changes here 
  ConsumerState<CounterCard> createState() => _CounterCardState();
}
//    Changes here 
class _CounterCardState extends ConsumerState<CounterCard> {
 ...
}
```
And that's it!
Now remember before I talked about a different kind of Provider and it was the `StateProvider`, it basically is an a `Provider` but it can maintain the State of its contents.
Now go above and add `State` to the `counterProvider`
```
//                                    Over Here
final counterProvider = StateProvider<int>((ref) {
  return 0;
});
```
Now go to `CounterCard` and let the `Text` watch the `counterProvider`
```
class _CounterCardState extends ConsumerState<CounterCard> {
  

  @override
  Widget build(BuildContext context) {
    return Card(
        child: ListTile(
      title: Text(ref.watch(counterProvider).toString()),
      trailing: IconButton(
        icon: const Icon(Icons.plus_one),
        onPressed: (){
          ...
        },
      ),
    ));
  }
}

```
Now in the `onPressed` we have to increment the "state" of `counterProvider`.
To do this we use `ref.read()` instead of `ref.watch`, so here it should be,
```
onPressed: () {
          setState(() {
            ref.read(counterProvider.state).state++;
          });
        },
```
Note that here it will still work if you don't use a `setState` Function.
That's it and now run the program to solve the State Mangement Problem we faced earlier.

I will be soon starting a Riverpod Series on Youtube so don't forget to subscribe my [Youtube Channel](https://www.youtube.com/channel/UCLmgkjCcj5t0QCZ9Ip-vpgw) and Also follow me on [Twitter](https://www.twitter.com/ChandramDutta) and [Instagram](https://www.instagram.com/flutter.zed) to get the latest updates and Tips and Tricks using Flutter.