Open In App

Flutter – Difference Between setState and Provider in State Management

Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we will look into how we can use state management or provider package for implementing state management in our flutter app. 

We are creating a simple counter app in flutter, which will help us in understanding state management in flutter application and deciding which is a better way to build our app and complete the project.

We will be discussing the two of the most important aspect required for understanding state management in the flutter app, called as setState and a package named provider.

Getting Started

We will begin with our basic flutter structure available by default. Create a stateless widget named Home Page and assign it to our home property of Material App.

Dart




import 'package:flutter/material.dart';
  
void main() => runApp(MyApp());
   
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Material App',
        home: HomePage()
      );
  }
}


Structure of our app

Inside the ‘Home Page‘ screen, we will make it a stateful widget, and it will be consisting of two buttons that will have the functionality of increasing and decreasing counter using set state functionality. And a floating action button that will navigate us to the second screen of our app, where will again keep the track of our variable itemCount.

Dart




class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}
  
class _HomePageState extends State<HomePage> {
  int itemCount = 0 ;
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.forward),
        onPressed: (){
          Navigator.push(context, MaterialPageRoute(builder: (_){
            return SecondPage(
              count: itemCount,
            );
          }));
        },
      ),
      body: Column(
        children: [
          Container(
            alignment: Alignment.center,
            height: 300.0,
            child: Text('$itemCount',style: TextStyle(fontSize: 30.0)),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              ElevatedButton(onPressed: (){
                setState(() {
                  itemCount++ ; 
                });
              }, child: Text('Add')),
              ElevatedButton(onPressed: (){
                setState(() {
                  itemCount-- ; 
                });
              }, child: Text('Delete'))
            ],
          )
        ],
      ),
    );
  }
}


Inside the second screen, we will again have the buttons for the increasing and decreasing counter. with the help of set State functionality  

It will be a stateful widget.

Dart




class SecondPage extends StatefulWidget {
  int count ;
  SecondPage({this.count}) ;
  
  @override
  _SecondPageState createState() => _SecondPageState();
}
  
class _SecondPageState extends State<SecondPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: [
          Container(
            alignment: Alignment.center,
            height: 300.0,
            child: Text('${widget.count}',style: TextStyle(fontSize: 30.0)),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              ElevatedButton(onPressed: (){
                setState(() {
                  widget.count++ ;
                });
              }, child: Text('Add')),
              ElevatedButton(onPressed: (){
                setState(() {
                  widget.count-- ;
                });
              }, child: Text('Delete'))
            ],
          )
        ],
      ),
    );
  }
}


On successfully running our code we can see that we do not get our desired outcome. The counter variable is not getting its correct value.

Output 

So to overcome this issue and to make better functionalities inside our app we will use the provider package. It is of great use when we have to deal with a multi-screen app where our data is changing dynamically, provider provides us a better facility of keeping our data to be updated with every function of our app. 

First import provider dependency inside pubspec.yaml file in our flutter app. 

Now create a class in another file extend this class to Change Notifier. This class will contain functionalities of increase and decrease the counter variable. Do not forget to include notify Listeners to our function else it will not work properly. Also, create a getter that will return the count variable. 

Dart




import 'package:flutter/material.dart';
  
class Manage extends ChangeNotifier{
    int count = 0 ;
  
    int get counter{
      return count ; 
    }
  
    void increaseCounter(){
      count++ ;
      notifyListeners();
    }
  
     void decreaseCounter(){
        count-- ;
        notifyListeners();
     }
}


To make our app aware and know about the providers we have to add something to our Material App inside main.dart. Wrap our Material App. Inside MultiProvider feature and inside it add our class to providers option of Multi Provider.  

Dart




class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider.value(value: Manage())
      ],
          child: MaterialApp(
        home: HomePage(),
      ),
    );
  }
}


Now the remaining and final task is to update something in our home page screen so that it can listen to our provider. 

First, make the home page a stateless widget. 

Dart




class HomePage extends StatelessWidget {
     
  @override
  Widget build(BuildContext context) {
    int itemCount = Provider.of<Manage>(context).counter;
  
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.forward),
        onPressed: (){
          Navigator.push(context, MaterialPageRoute(builder: (_){
            return SecondPage();
          }));
        },
      ),
      body: Column(
        children: [
          Container(
            alignment: Alignment.center,
            height: 300.0,
            child: Text('$itemCount',style: TextStyle(fontSize: 30.0)),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              ElevatedButton(onPressed: (){
                Provider.of<Manage>(context,listen:false).increaseCounter();
              }, child: Text('Add')),
              ElevatedButton(onPressed: (){
                Provider.of<Manage>(context,listen:false).decreaseCounter();
              }, child: Text('Delete'))
            ],
          )
        ],
      ),
    );
  }
}


Ensure to make the value of listen argument to be false inside the provider used to call the functions.  We will make it true only when we have to use the value or listen to the value in our app screen. (Like the value of itemCount)

Similarly, we can update our Second Page widget accordingly.Convert it to a stateless widget 

Dart




class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
   int itemCount  = Provider.of<Manage>(context).counter ; 
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: [
          Container(
            alignment: Alignment.center,
            height: 300.0,
            child: Text('$itemCount',style: TextStyle(fontSize: 30.0)),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              ElevatedButton(onPressed: (){
                Provider.of<Manage>(context,listen: false).increaseCounter();
              }, child: Text('Add')),
              ElevatedButton(onPressed: (){
                Provider.of<Manage>(context,listen: false).decreaseCounter();
              }, child: Text('Delete'))
            ],
          )
        ],
      ),
    );
  }
}


Output 

Hence we can see that provider does our job pretty well and is easy to use. 



Last Updated : 19 Apr, 2021
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads