Flutter Adding products items into shoping cart in an e-commerce app with ChangeNotifier Provider
Last updated May 09, 2021In 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.
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 :
|
|
|
|
4564 Views |