Flutter Adding products items into shoping cart in an e-commerce app with ChangeNotifier Provider

Last updated May 09, 2021

In this post, we are going to learn about Providers in a flutter with example of how to add products items into shoping cart in e-commerce app. How to handle Data changes in the Application.

What is Provider?

The provider is a way to handle State management in flutter applications. Like the Inherited widget, we can handle the data changes with providers.

Let' check a simple Cart page where we are facing the issue of updating the Cart Items,

 

This Cart application tw0 pages 

HomePage : Which contains all items and Cart count in the top

CartPage : Which contains all cart items with Remove option.

 

 

HomePage:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_provider/CartPage.dart';
import 'package:flutter_provider/utils.dart';

void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: MyHomePage()
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);


  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {

  @override
  void initState() {
    // TODO: implement initState
    super.initState();

  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.green,
          title: Text("Shoping Cart"),
          actions: [
            Padding(
              padding: const EdgeInsets.only(right:16.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  Stack(children: [
                    IconButton(icon:Icon( Icons.add_shopping_cart), onPressed: (){
                      Navigator.push(context, MaterialPageRoute(builder: (context)=> CartPage()));

                    },),
                    (Cart().getList().length>0)?Positioned(
                      top: 5,
                      right: 5,
                      child: Container(
                          decoration: BoxDecoration(
                              color: Colors.red,
                              borderRadius: BorderRadius.all(Radius.circular(10))
                          ),
                          child: Padding(
                            padding: const EdgeInsets.all(3.0),
                            child: Text(Cart().getList().length.toString()),
                          )),
                    ):Text("")
                  ],),
                  InkWell(onTap: (){},child: Center(child: Text("SignIn",style: TextStyle(fontSize: 20),)),)
                ],
              ),
            )
          ],
        ),
        body:ListView(
          scrollDirection: Axis.vertical,
          children: [
            Container(
              padding: EdgeInsets.all(2),
              decoration: BoxDecoration(
                  borderRadius: BorderRadius.all(Radius.circular(
                      5
                  )),
                  border: Border.all(
                      color: Colors.green,width: 1
                  )
              ),
              height: 220,
              child: Image.asset("images/book.png",fit: BoxFit.fitHeight,),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text("Top courses",style: TextStyle(fontSize: 20,fontWeight: FontWeight.bold,color: Colors.red),),
            ),
            Container(
              height: 200,
              child: ListView.builder(
                  scrollDirection: Axis.horizontal,
                  itemCount: 10,
                  itemBuilder: (context,index){
                    return Container(
                      width: 200,

                      child: Card(
                        child: Stack(

                          children: [
                            //Image.network("https://www.tutorix.com/images/class_7_blood_and_blood_vessels.jpg"),
                            Image.network("https://www.tutorialspoint.com/videotutorials/assets/videos/courses/173/images/course_173_image.png"),
                            Positioned(
                              bottom: 0,
                              left: 0,
                              right: 0,
                              child: Column(
                                mainAxisSize: MainAxisSize.max,
                                mainAxisAlignment: MainAxisAlignment.spaceAround,
                                children: [
                                  //Text("Product Name",style: TextStyle(color: Colors.green,fontWeight:  FontWeight.bold,fontSize: 20),),
                                  FlatButton(onPressed: (){
                                    setState(() {
                                      print(Cart().getList().length);
                                      Cart().addCart(index);
                                    });

                                  }, child: Text("Add To Cart",style: TextStyle(color: Colors.white),),color: Colors.green,)
                                ],
                              ),
                            )


                          ],
                        ),
                      ),
                    );
                  }),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text("Video courses",style: TextStyle(fontSize: 20,fontWeight: FontWeight.bold,color: Colors.red),),
            ),
            Container(
              decoration: BoxDecoration(
                  borderRadius: BorderRadius.all(Radius.circular(
                      5
                  )),
                  border: Border.all(
                      color: Colors.black26,width: 2
                  )
              ),

              height: 220,
              child: Image.network("https://www.tutorialspoint.com/videotutorials/assets/videos/courses/525/images/course_525_image.jpg",fit: BoxFit.fitWidth,),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text("Popular courses",style: TextStyle(fontSize: 20,fontWeight: FontWeight.bold,color: Colors.red),),
            ),
            Container(
              height: 200,
              child: ListView.builder(
                  scrollDirection: Axis.horizontal,
                  itemCount: 10,
                  itemBuilder: (context,index){
                    return Container(
                      width: 200,

                      child: Padding(
                        padding: const EdgeInsets.all(2.0),
                        child: Card(
                          child: Stack(

                            children: [
                              //Image.network("https://www.tutorix.com/images/class_7_blood_and_blood_vessels.jpg"),
                              Image.network("https://www.tutorialspoint.com/videotutorials/assets/videos/courses/174/images/course_174_image.png",),
                              Positioned(
                                bottom: 0,
                                left: 0,
                                right: 0,
                                child: Column(
                                  mainAxisSize: MainAxisSize.max,
                                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                                  children: [
                                    // Text("Product Name",style: TextStyle(color: Colors.green,fontWeight:  FontWeight.bold,fontSize: 20),),
                                    FlatButton(onPressed: (){}, child: Text("Add To Cart",style: TextStyle(color: Colors.white),),color: Colors.green,)
                                  ],
                                ),
                              )


                            ],
                          ),
                        ),
                      ),
                    );
                  }),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text("Popular courses",style: TextStyle(fontSize: 20,fontWeight: FontWeight.bold,color: Colors.red),),
            ),
            Container(
              height: 200,
              child: ListView.builder(
                  scrollDirection: Axis.horizontal,
                  itemCount: 10,
                  itemBuilder: (context,index){
                    return Container(
                      width: 200,

                      child: Padding(
                        padding: const EdgeInsets.all(2.0),
                        child: Card(
                          child: Stack(

                            children: [
                              //Image.network("https://www.tutorix.com/images/class_7_blood_and_blood_vessels.jpg"),
                              Image.network("https://www.tutorialspoint.com/videotutorials/assets/videos/courses/174/images/course_174_image.png",),
                              Positioned(
                                bottom: 0,
                                left: 0,
                                right: 0,
                                child: Column(
                                  mainAxisSize: MainAxisSize.max,
                                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                                  children: [
                                    // Text("Product Name",style: TextStyle(color: Colors.green,fontWeight:  FontWeight.bold,fontSize: 20),),
                                    FlatButton(onPressed: (){}, child: Text("Add To Cart",style: TextStyle(color: Colors.white),),color: Colors.green,)
                                  ],
                                ),
                              )


                            ],
                          ),
                        ),
                      ),
                    );
                  }),
            ),
          ],
        )// This trailing comma makes auto-formatting nicer for build methods.

    );
  }
}

 

CartPage

 

import 'package:flutter/material.dart';
import 'package:flutter_provider/utils.dart';


class CartPage extends StatefulWidget{
  @override
  State createState() {
    // TODO: implement createState
   return CartPageState();
  }

}

class CartPageState extends State{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("Cart Items"),backgroundColor: Colors.green,),
      body:( Cart().getList().length>0) ?GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
          itemCount: Cart().getList().length,
          itemBuilder: (context,index){
            return Container(
              width: 200,

              child: Card(
                child: Stack(

                  children: [
                    //Image.network("https://www.tutorix.com/images/class_7_blood_and_blood_vessels.jpg"),
                    Image.network("https://www.tutorialspoint.com/videotutorials/assets/videos/courses/173/images/course_173_image.png"),
                    Positioned(
                      bottom: 0,
                      left: 0,
                      right: 0,
                      child: Column(
                        mainAxisSize: MainAxisSize.max,
                        mainAxisAlignment: MainAxisAlignment.spaceAround,
                        children: [
                          //Text("Product Name",style: TextStyle(color: Colors.green,fontWeight:  FontWeight.bold,fontSize: 20),),
                          FlatButton(onPressed: (){
                            setState(() {
                              print(Cart().getList().length);
                              Cart().getList().removeAt(index);
                            });

                          }, child: Text("Remove",style: TextStyle(color: Colors.white),),color: Colors.green,)
                        ],
                      ),
                    )


                  ],
                ),
              ),
            );
          }):Center(child: Text("No Items found in Cart", style: TextStyle(color: Colors.red,fontSize: 20),),),
    );
  }

}

 

Utils page

import 'package:flutter/material.dart';


class Cart  {
  static List list=List.empty(growable: true);

   addCart(int pos)
  {
    list.add(pos);

  }

   List getList()
  {
    return list;

  }

  removeItem(index)
  {
    list.removeAt(index);

  }
}

 

If we run the application it will show home screen, when we add items to cart all items will add in cart and update cart count on Appbar  and the cartpage will show all items.

let's try to remove items in CartPage, there is it will update cart items, now come to homepage and check the count of cart in Appbar, it will show previous count, means the removed cart items not updated in homescreen.

 

ChangeNotifier

 

 

Now how we will fix this issue, here Providers will help us to fix this issue.

For this example, we are using ChangeNotifierProvider

.

Let's add the provider library in pubspec.yaml file

 

dependencies:
  provider:
  flutter:
    sdk: flutter

 

 

Now update all above three class with  ChangeNotifierProvider 

Notifiers:

These handle notifying the Providers that something has changed. Which one depend on what we are  trying to listen for. A ChangeNofier is going to notify of any changes in the class, as it is tracking the object as a whole. We can only use one of these with any one Type/Object/Model.

 

ChangeNotifier

ChangeNotifier uses the notifyListeners function whenever there is any change in the class/model/object

 

ValueNotifier

A [ChangeNotifier] that holds a single value. When [value] is replaced with something that is not equal to the old value as evaluated by the equality operator ==, this class notifies its listeners.

 

 

Providers : we have below providers.

  • Provider

  • ChangeNotifierProvider

  • MultiProvider

  • StreamProvider
  • FutureProvider

 

To fix our above issue we are going to use ChangeNotifiedProvider.

After all changes in above Pages will looks like below

 

HomePage

import 'package:flutter/material.dart';
import 'package:flutter_provider/CartPage.dart';
import 'package:flutter_provider/utils.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(
      ChangeNotifierProvider(create: (context)=>Cart(),child:  MyApp(),)
  );
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: MyHomePage()
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);


  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State {

  @override
  void initState() {
    // TODO: implement initState
    super.initState();

  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.green,
          title: Text("Shoping Cart"),
          actions: [
            Padding(
              padding: const EdgeInsets.only(right:16.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  Stack(children: [
                    IconButton(icon:Icon( Icons.add_shopping_cart), onPressed: (){
                      Navigator.push(context, MaterialPageRoute(builder: (context)=> CartPage()));

                    },),
                    (Cart().getList().length>0)?Positioned(
                      top: 5,
                      right: 5,
                      child: Container(
                          decoration: BoxDecoration(
                              color: Colors.red,
                              borderRadius: BorderRadius.all(Radius.circular(10))
                          ),
                          child: Padding(
                            padding: const EdgeInsets.all(3.0),
                            child: Consumer(builder: (context,cart,child)=>Text(cart.getList().length.toString()),),
                          )),
                    ):Text("")
                  ],),
                  InkWell(onTap: (){},child: Center(child: Text("SignIn",style: TextStyle(fontSize: 20),)),)
                ],
              ),
            )
          ],
        ),
        body:ListView(
          scrollDirection: Axis.vertical,
          children: [
            Container(
              padding: EdgeInsets.all(2),
              decoration: BoxDecoration(
                  borderRadius: BorderRadius.all(Radius.circular(
                      5
                  )),
                  border: Border.all(
                      color: Colors.green,width: 1
                  )
              ),
              height: 220,
              child: Image.asset("images/book.png",fit: BoxFit.fitHeight,),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text("Top courses",style: TextStyle(fontSize: 20,fontWeight: FontWeight.bold,color: Colors.red),),
            ),
            Container(
              height: 200,
              child: ListView.builder(
                  scrollDirection: Axis.horizontal,
                  itemCount: 10,
                  itemBuilder: (context,index){
                    return Container(
                      width: 200,

                      child: Card(
                        child: Stack(

                          children: [
                            //Image.network("https://www.tutorix.com/images/class_7_blood_and_blood_vessels.jpg"),
                            Image.network("https://www.tutorialspoint.com/videotutorials/assets/videos/courses/173/images/course_173_image.png"),
                            Positioned(
                              bottom: 0,
                              left: 0,
                              right: 0,
                              child: Column(
                                mainAxisSize: MainAxisSize.max,
                                mainAxisAlignment: MainAxisAlignment.spaceAround,
                                children: [
                                  //Text("Product Name",style: TextStyle(color: Colors.green,fontWeight:  FontWeight.bold,fontSize: 20),),
                                  Consumer(builder: (context,cart,child)=>FlatButton(onPressed: (){
                                    cart.addCart(index);

                                  }, child: Text("Add To Cart",style: TextStyle(color: Colors.white),),color: Colors.green,),)
                                ],
                              ),
                            )


                          ],
                        ),
                      ),
                    );
                  }),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text("Video courses",style: TextStyle(fontSize: 20,fontWeight: FontWeight.bold,color: Colors.red),),
            ),
            Container(
              decoration: BoxDecoration(
                  borderRadius: BorderRadius.all(Radius.circular(
                      5
                  )),
                  border: Border.all(
                      color: Colors.black26,width: 2
                  )
              ),

              height: 220,
              child: Image.network("https://www.tutorialspoint.com/videotutorials/assets/videos/courses/525/images/course_525_image.jpg",fit: BoxFit.fitWidth,),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text("Popular courses",style: TextStyle(fontSize: 20,fontWeight: FontWeight.bold,color: Colors.red),),
            ),
            Container(
              height: 200,
              child: ListView.builder(
                  scrollDirection: Axis.horizontal,
                  itemCount: 10,
                  itemBuilder: (context,index){
                    return Container(
                      width: 200,

                      child: Padding(
                        padding: const EdgeInsets.all(2.0),
                        child: Card(
                          child: Stack(

                            children: [
                              //Image.network("https://www.tutorix.com/images/class_7_blood_and_blood_vessels.jpg"),
                              Image.network("https://www.tutorialspoint.com/videotutorials/assets/videos/courses/174/images/course_174_image.png",),
                              Positioned(
                                bottom: 0,
                                left: 0,
                                right: 0,
                                child: Column(
                                  mainAxisSize: MainAxisSize.max,
                                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                                  children: [
                                    // Text("Product Name",style: TextStyle(color: Colors.green,fontWeight:  FontWeight.bold,fontSize: 20),),
                                    FlatButton(onPressed: (){}, child: Text("Add To Cart",style: TextStyle(color: Colors.white),),color: Colors.green,)
                                  ],
                                ),
                              )


                            ],
                          ),
                        ),
                      ),
                    );
                  }),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: Text("Popular courses",style: TextStyle(fontSize: 20,fontWeight: FontWeight.bold,color: Colors.red),),
            ),
            Container(
              height: 200,
              child: ListView.builder(
                  scrollDirection: Axis.horizontal,
                  itemCount: 10,
                  itemBuilder: (context,index){
                    return Container(
                      width: 200,

                      child: Padding(
                        padding: const EdgeInsets.all(2.0),
                        child: Card(
                          child: Stack(

                            children: [
                              //Image.network("https://www.tutorix.com/images/class_7_blood_and_blood_vessels.jpg"),
                              Image.network("https://www.tutorialspoint.com/videotutorials/assets/videos/courses/174/images/course_174_image.png",),
                              Positioned(
                                bottom: 0,
                                left: 0,
                                right: 0,
                                child: Column(
                                  mainAxisSize: MainAxisSize.max,
                                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                                  children: [
                                    // Text("Product Name",style: TextStyle(color: Colors.green,fontWeight:  FontWeight.bold,fontSize: 20),),
                                    FlatButton(onPressed: (){}, child: Text("Add To Cart",style: TextStyle(color: Colors.white),),color: Colors.green,)
                                  ],
                                ),
                              )


                            ],
                          ),
                        ),
                      ),
                    );
                  }),
            ),
          ],
        )// This trailing comma makes auto-formatting nicer for build methods.

    );
  }
}

 

 

CartPage

import 'package:flutter/material.dart';
import 'package:flutter_provider/utils.dart';
import 'package:provider/provider.dart';


class CartPage extends StatefulWidget{
  @override
  State createState() {
    // TODO: implement createState
    return CartPageState();
  }
}
class CartPageState extends State{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text("Cart Items"),backgroundColor: Colors.green,),
      body:Consumer(builder: (context,cart,child)=>( cart.getList().length>0) ?GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
          itemCount: cart.getList().length,
          itemBuilder: (context,index){
            return Container(
              width: 200,

              child: Card(
                child: Stack(

                  children: [
                    //Image.network("https://www.tutorix.com/images/class_7_blood_and_blood_vessels.jpg"),
                    Image.network("https://www.tutorialspoint.com/videotutorials/assets/videos/courses/173/images/course_173_image.png"),
                    Positioned(
                      bottom: 0,
                      left: 0,
                      right: 0,
                      child: Column(
                        mainAxisSize: MainAxisSize.max,
                        mainAxisAlignment: MainAxisAlignment.spaceAround,
                        children: [
                          //Text("Product Name",style: TextStyle(color: Colors.green,fontWeight:  FontWeight.bold,fontSize: 20),),
                          FlatButton(onPressed: (){
                            cart.removeItem(index);

                          }, child: Text("Remove",style: TextStyle(color: Colors.white),),color: Colors.green,)
                        ],
                      ),
                    )


                  ],
                ),
              ),
            );
          }):Center(child: Text("No Items found in Cart", style: TextStyle(color: Colors.red,fontSize: 20),),),
      ),);
  }

}

 

Utils Page

import 'package:flutter/material.dart';


class Cart extends ChangeNotifier  {
  static List list=List.empty(growable: true);

   addCart(int pos)
  {
    list.add(pos);
   notifyListeners();
  }

   List getList()
  {
    return list;

  }

  removeItem(index)
  {
    list.removeAt(index);

    notifyListeners();
  }
}

 

Article Contributed By :
https://www.rrtutors.com/site_assets/profile/assets/img/avataaars.svg

4312 Views