Flutter Provider State Management

Flutter Provider State Management

    In general if you use Provider for State Management, you should use ChangeNotifierProvider to wrap your material app. 

     

    ChangeNotifier

    Your class should extend ChangeNotifier, if you want to use Provider package in your app. In our class, we created a class named DataClass, and this class extends ChangeNotifier.

    Consumer

    You need to wrap your widget, using Consumer. It helps you to show the changed data in the UI or View.

    Consumer<DataClass>(builder: (context, data, child){
                      return Text('${data.x}', style: TextStyle(
                        fontSize: 20,fontWeight: FontWeight.bold
                      ),);
                    })

    Here it takes three properties

    context

    Context is created with with ChangeNotifierProvider. See the below section

    data

    It's an instance of DataClass. With data, you can access the properties of DataClass

    child

    It refers to the widget itself.

    Provider.of<>()

    Provider.of<>() can access the data that's inside DataClass( this class extends ChangeNotifier). It's job is to read the data from DataClass. 

    See the complete syntax

    Provider.of<DataClass>(context, listen:false).incrementX()

    Here it takes two properties

    context

    Context is created with with ChangeNotifierProvider. See the below section

    listen

    We need to set listen:false. The default is true.

    ChangeNotifierProvider

    This is used in the entry point of your app. Instead of wrapping your app using MaterialApp, you need to wrap your app using ChangeNotifierProvider like below

      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return ChangeNotifierProvider(create: (context)=>DataClass(),
        child: GetMaterialApp(
            debugShowCheckedModeBanner: false,
            title: 'Flutter Demo',
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            home: const HomePage()
        ),);
      }

    You see ChangeNotifierProvider also takes two properties.

    create

    It takes your class That extends ChangeNotifier.

    child

    It takes MaterialApp.

     

    Which should look like below

    import 'package:flutter/material.dart';
    import 'package:get/get.dart';
    import 'package:provider/provider.dart';
    import 'package:provider_test/home_page.dart';
    
    import 'data_class.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
    
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return ChangeNotifierProvider(create: (context)=>DataClass(),
        child: GetMaterialApp(
            debugShowCheckedModeBanner: false,
            title: 'Flutter Demo',
            theme: ThemeData(
              primarySwatch: Colors.blue,
            ),
            home: const HomePage()
        ),);
      }
    }

     

    Home page home_page.dart

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:get/get.dart';
    import 'package:provider/provider.dart';
    import 'package:provider_test/second_page.dart';
    
    import 'data_class.dart';
    
    class HomePage extends StatelessWidget {
      const HomePage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: const Color(0xFFfefcff),
          body: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children:  [
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 40),
                child: Row(
                  children: [
                    Consumer<DataClass>(builder: (context, data, child){
                      return Text('${data.x}', style: TextStyle(
                        fontSize: 20,fontWeight: FontWeight.bold
                      ),);
                    }),
                    Spacer(),
                    Text("Total", style: TextStyle(fontWeight: FontWeight.bold,
                    fontSize: 40),)
                  ],
                ),
              ),
              SizedBox(height: 100,),
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 40),
                child: Row(
                  children: [
    
                    GestureDetector(child: Container(
                      width: 60,
                      height: 60,
                      child: Icon(Icons.add),
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(10),
    
                          border: Border.all(
                              color: Color(0xFF716f72),
                              width: 1
                          )
                      ),
                    ),
                    onTap: (){
                      if(context.read<DataClass>().x>=5){
                        Get.snackbar("Item", "Can not more than this",
                            backgroundColor: Colors.black,
                            colorText: Colors.white,
                            titleText: Text(
                              "Item",
                              style: TextStyle(
                                  fontSize: 40,
                                  color: Colors.white
                              ),
                            ),
                            messageText: Text(
                              "Can not be more than this",
                              style: TextStyle(
                                  fontSize: 20,
                                  color: Colors.white
                              ),
                            )
                        );
                      }else{
                        context.read<DataClass>().incrementX();
                      }
                    },),
                    Spacer(),
                    Container(
                      height: 60,
                      width: 200,
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(10),
    
                          color: Colors.black
                      ),
                      child: Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 10),
                        child: Row(
    
                          children: [
                            GestureDetector(
                                onTap: (){
                                  Get.to(()=>SecondPage(), transition: Transition.upToDown, duration: Duration(seconds: 1));
                                },
                                child: Text("Next Page", style: TextStyle(fontSize: 20, color: Colors.white),)),
                            Spacer(),
                            Icon(Icons.skip_next, color:Colors.white)
                          ],
                        ),
                      ),
                    )
                  ],
                ),
              )
            ]
          ),
        );
      }
    }
    

     

    Second page second_page.dart

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:get/get.dart';
    import 'package:provider/provider.dart';
    import 'package:provider_test/home_page.dart';
    
    import 'data_class.dart';
    
    class SecondPage extends StatelessWidget {
      const SecondPage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: const Color(0xFFfefcff),
          body: Container(
              width: double.maxFinite,
              height: double.maxFinite,
              child:Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Flexible(
                    child: Container(
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceAround,
                        children: [
    
                          Consumer<DataClass>(builder: (context, data, child){
                            return Text('${data.x}', style: TextStyle(
                              fontWeight: FontWeight.bold,
                              fontSize: 20,
                            ),);
                          }),
                          const Text(
                            "-- Total",
                            style: TextStyle(
                                fontSize: 40,
                                fontWeight: FontWeight.bold
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                  SizedBox(height: 100,),
                  Container(
    
                    width: double.maxFinite,
                    margin: const EdgeInsets.only(left: 40, right: 40),
                    child: Row(
                      children: [
                          GestureDetector(
                            onTap:(){
                             if(Provider.of<DataClass>(context, listen: false).x<=0){
                               Get.snackbar("Item", "Can not decrease more",
                                backgroundColor: Colors.black,
                                 colorText: Colors.white,
                                 titleText: Text(
                                   "Item",
                                   style: TextStyle(
                                     fontSize: 40,
                                     color: Colors.white
                                   ),
                                 ),
                                 messageText: Text(
                                   "Can not reduce more",
                                   style: TextStyle(
                                       fontSize: 20,
                                       color: Colors.white
                                   ),
                                 )
                               );
                             }else{
                               Provider.of<DataClass>(context, listen: false).decrementX();
                             }
                          },
                            child: Container(
                              height:60,
                              width: 60,
                              child: const Icon(Icons.remove),
                              decoration: BoxDecoration(
    
                                borderRadius: BorderRadius.circular(10),
                                border: Border.all(
                                  width: 1,
                                  color: const Color(0xFF716f72)
                                )
                              ),
                            ),
                          ),
                        const SizedBox(width: 20,),
                        Flexible(child:  Container(
                          padding: const EdgeInsets.only(left: 20, right: 20),
                          child: GestureDetector(
                            onTap: (){
                              Get.to(()=>HomePage(), transition: Transition.downToUp, duration: Duration(seconds: 1));
                            },
                            child: Row(
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
                              children: const [
                                Icon(Icons.skip_previous, color:Color(0xFFfefeff)),
                                Text("Prev Page", style: TextStyle(
                                    fontSize: 20,color:Color(0xFFfefeff)
                                ),),
                              ],
                            ),
                          ),
                          height:60,
                          width: double.maxFinite,
                          decoration: BoxDecoration(
                            color: Colors.black,
                            borderRadius: BorderRadius.circular(10),
                          ),
                        ),)
                      ],
                    ),
                  )
                ],
              )
          ),
        );
      }
    }
    

     

    Provider class data_class.dart

    import 'package:flutter/cupertino.dart';
    
    class DataClass extends ChangeNotifier{
      int _x=0;
      int get x => _x;
      void incrementX(){
        _x++;
        notifyListeners();
      }
    
      void decrementX(){
        _x--;
        notifyListeners();
      }
    }

    You see inside build method, we are using ChangeNotifierProvider. And we are also passing our Provider which is DataClass in an anonymous function.

     

    There are few similarities that you need to know
    final model = context.read<Model>();
This returns the Model without listening for any changes.
    final model = context.watch<Model>();
This makes the widget listen for changes on the Model.
    final model = Provider.of<Model>(context, listen: false);
This works the same as context.read<Model>();
    final model = Provider.of<Model>(context);
This works the same as context.watch<Model>();

    Courses


    Recent posts