Flutter - Difference Between setState and Provider in State Management - GeeksforGeeks

19 Apr, 2021
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.
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()      );  }}
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. 
Flutter
Dart
Difference Between
Flutter
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Flutter - Custom Bottom Navigation Bar
ListView Class in Flutter
Flutter - Flexible Widget
Flutter - Stack Widget
Android Studio Setup for Flutter Development
Difference between BFS and DFS
Class method vs Static method in Python
Differences between TCP and UDP
Difference between var, let and const keywords in JavaScript
Differences between IPv4 and IPv6