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>();