How to get array data back to mobile screen from firebase (Flutter) - firebase

How to get back array data to the mobile screen.
The String in the firebase is retrieved easily but I have problem with array data.
1) main.dart :
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'firestoreservice.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'taskscreen.dart';
import 'task.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter ToDo APP',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Color(0xff543B7A),
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<Task> items;
FirestoreService fireServ = new FirestoreService();
StreamSubscription<QuerySnapshot> todoTasks;
#override
void initState() {
super.initState();
items=new List();
todoTasks?.cancel();
todoTasks=fireServ.getTaskList().listen((QuerySnapshot snapshot){
final List<Task> tasks=snapshot.documents
.map((documentSnapshot) => Task. fromMap(documentSnapshot.data))
.toList();
setState(() {
this.items = tasks;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: Column(
children: <Widget>[
_myAppBar(context),
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height - 80,
child: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return Stack(children: <Widget>[
// The containers in the background
Column(children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 8.0, right: 8.0),
child: Container(
width: MediaQuery.of(context).size.width,
height: 80.0,
child: Padding(
padding: EdgeInsets.only(top: 8.0, bottom: 8.0),
child: Material(
color: Colors.white,
elevation: 14.0,
shadowColor: Color(0x802196F3),
child: Center(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'${items[index].name}',
style: TextStyle(
color: Colors.black,
fontSize: 20.0),
),
Text(
'${items[index].size}',
style: TextStyle(
color: Colors.black,
fontSize: 20.0),
),
Container(
child: Image.network(
'${items[index].imageU}',
)),
],
),
),
),
),
),
),
),
]),
]);
}),
),
],
),
);
}
Widget todoType(String icontype) {
IconData iconval;
Color colorval;
switch (icontype) {
case 'travel':
iconval = FontAwesomeIcons.mapMarkerAlt;
colorval = Color(0xff4158ba);
break;
case 'shopping':
iconval = FontAwesomeIcons.shoppingCart;
colorval = Color(0xfffb537f);
break;
case 'gym':
iconval = FontAwesomeIcons.dumbbell;
colorval = Color(0xff4caf50);
break;
case 'party':
iconval = FontAwesomeIcons.glassCheers;
colorval = Color(0xff9962d0);
break;
default:
iconval = FontAwesomeIcons.tasks;
colorval = Color(0xff0dc8f5);
//
}
return CircleAvatar(
backgroundColor: colorval,
child: Icon(iconval, color: Colors.white, size: 20.0),
);
}
Widget _myAppBar(context) {
return Container(
height: 80.0,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
const Color(0xFFFA7397),
const Color(0xFFFDDE42),
],
begin: const FractionalOffset(0.0, 0.0),
end: const FractionalOffset(1.0, 0.0),
stops: [0.0, 1.0],
tileMode: TileMode.clamp),
),
child: Padding(
padding: const EdgeInsets.only(top: 16.0),
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Expanded(
flex: 5,
child: Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'ToDo Tasks',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 20.0),
),
),
),
),
Expanded(
flex: 1,
child: Container(
child: IconButton(
icon: Icon(
FontAwesomeIcons.search,
color: Colors.white,
),
onPressed: () {
//
}),
),
),
],
)),
),
);
}
}
2) task.dart
class Task{
String _name;
String _size;
Task(this._name ,this._size);
Task.map(dynamic obj){
this._name = obj['name'];
this._size=obj['size'];
List<String> imageU= new List<String>();
}
String get name=> _name;
String get size=>_size;
Task.fromMap(Map<String,dynamic> map){
this._name = map['name'];
this._size= map['size'];
this.imageU= List.from(map['images']);
}
}
3) firestoreservice.dart
import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'task.dart';
final CollectionReference myCollection =
Firestore.instance.collection('products');
class FirestoreService {
Future<Task> createTODOTask(String name, String size) async {
final TransactionHandler createTransaction = (Transaction tx) async {
final DocumentSnapshot ds = await tx.get(myCollection.document());
};
return Firestore.instance.runTransaction(createTransaction).then((mapData) {
return Task.fromMap(mapData);
}).catchError((error) {
print('error: $error');
return null;
});
}
Stream<QuerySnapshot> getTaskList({int offset, int limit}) {
Stream<QuerySnapshot> snapshots = myCollection.snapshots();
if (offset != null) {
snapshots = snapshots.skip(offset);
}
if (limit != null) {
snapshots = snapshots.take(limit);
}
return snapshots;
}
}
How to get back array data to the mobile screen. The String in the firebase is retrieved easily but I have a problem with array data.

Convert task.dart to see what solution will work:
class Task{
String name;
List<String> size= new List<String>();
Task.fromMap(Map<String,dynamic> map){
this.name = map['name'];
this.size= List.from(map['size' ]);
}
}
And make sure all the documents in the image have "size" field.

Related

I cannot retrieve and view data from Firestore Flutter

#HOME: this is home linked to FeatureProducts()
And I cannot retrieve data "product", it always return nil.
I want to retrieve data from Firebase into the Listview.
this is my firebase cloud fire store Image of Firebase Database
i try many time with many ways and all codes doesn't give any errors, but When i run the app and open the activity the data cannot show they will be empty,
import 'package:farmers_ecommerce/commons/common.dart';
import 'package:farmers_ecommerce/db/product.dart';
import 'package:farmers_ecommerce/pages/product_search.dart';
import 'package:farmers_ecommerce/provider/product.dart';
import 'package:farmers_ecommerce/provider/user_provider.dart';
import 'package:farmers_ecommerce/widget/featured_products.dart';
import 'package:farmers_ecommerce/widget/product_card.dart';
import 'package:farmers_ecommerce/widgets/custom_text.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'cart.dart';
import 'order.dart';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final _key = GlobalKey<ScaffoldState>();
ProductServices _productServices = ProductServices();
#override
Widget build(BuildContext context) {
final userProvider = Provider.of<UserProvider>(context);
final productProvider = Provider.of<ProductProvider>(context);
return Scaffold(
key: _key,
backgroundColor: Colors.white,
endDrawer: Drawer(
child: ListView(
children: <Widget>[
UserAccountsDrawerHeader(
decoration: BoxDecoration(color: Colors.black),
accountName: CustomText(
text: userProvider.userModel?.name ?? "username lading...",
color: Colors.white,
weight: FontWeight.bold,
size: 18,
),
accountEmail: CustomText(
text: userProvider.userModel?.email ?? "email loading...",
color: Colors.white,
),
),
ListTile(
onTap: () async{
await userProvider.getOrders();
changeScreen(context, OrdersScreen());
},
leading: Icon(Icons.bookmark_border),
title: CustomText(text: "My orders"),
),
ListTile(
onTap: () async{
userProvider.signOut();
},
leading: Icon(Icons.exit_to_app),
title: CustomText(text: "Log out"),
),
],
),
),
body: SafeArea(
child: ListView(
children: <Widget>[
// Custom App bar
Stack(
children: <Widget>[
Positioned(
top: 10,
right: 20,
child: Align(
alignment: Alignment.topRight,
child: GestureDetector(
onTap: () {
_key.currentState.openEndDrawer();
},
child: Icon(Icons.menu))),
),
Positioned(
top: 10,
right: 60,
child: Align(
alignment: Alignment.topRight,
child: GestureDetector(
onTap: (){
changeScreen(context, CartScreen());
},
child: Icon(Icons.shopping_cart))),
),
Positioned(
top: 10,
right: 100,
child: Align(
alignment: Alignment.topRight, child: GestureDetector(
onTap: (){
_key.currentState.showSnackBar(SnackBar(
content: Text("User profile")));
},
child: Icon(Icons.person))),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'What are\nyou Shopping for?',
style: TextStyle(
fontSize: 30,
color: Colors.black.withOpacity(0.6),
fontWeight: FontWeight.w400),
),
),
],
),
// Search Text field
// Search(),
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
bottomRight: Radius.circular(20),
bottomLeft: Radius.circular(20))),
child: Padding(
padding: const EdgeInsets.only(
top: 8, left: 8, right: 8, bottom: 10),
child: Container(
decoration: BoxDecoration(
color: Colors.grey.withOpacity(0.2),
borderRadius: BorderRadius.circular(20),
),
child: ListTile(
leading: Icon(
Icons.search,
color: Colors.black,
),
title: TextField(
textInputAction: TextInputAction.search,
onSubmitted: (pattern)async{
await productProvider.search(productName: pattern);
changeScreen(context, ProductSearchScreen());
},
decoration: InputDecoration(
hintText: "fashion....",
border: InputBorder.none,
),
),
),
),
),
),
// featured products
Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(14.0),
child: Container(
alignment: Alignment.centerLeft,
child: new Text('Featured products')),
),
],
),
FeaturedProducts(),
**this is the feature products. i cannot see any thing on here.
its blank**
// recent products
Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(14.0),
child: Container(
alignment: Alignment.centerLeft,
child: new Text('Recent products')),
),
],
),
Column(
children: productProvider.products
.map((item) => GestureDetector(
child: ProductCard(
product: item,
),
))
.toList(),
)
],
),
),
);
}
}
#FEATURED PRODUCT: this is linked to ProductProvider which listens from the
database
import 'package:farmers_ecommerce/provider/product.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'featured_card.dart';
class FeaturedProducts extends StatefulWidget {
#override
_FeaturedProductsState createState() => _FeaturedProductsState();
}
class _FeaturedProductsState extends State<FeaturedProducts> {
#override
Widget build(BuildContext context) {
final productProvider = Provider.of<ProductProvider>(context);
return Container(
height: 230,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: productProvider.products.length,
itemBuilder: (_, index) {
return FeaturedCard(
product: productProvider.products[index],
);
}));
}
}
#PRODUCT PROVIDER
//i feel the provider is not loading any products
import 'package:farmers_ecommerce/db/product.dart';
import 'package:farmers_ecommerce/models/product.dart';
import 'package:flutter/material.dart';
class ProductProvider with ChangeNotifier{
ProductServices _productServices = ProductServices();
List<ProductModel> products = [];
List<ProductModel> productsSearched = [];
ProductProvider.initialize(){
loadProducts();
}
loadProducts()async{enter code here
products = await _productServices.getProducts();
notifyListeners();
}
Future search({String productName})async{
productsSearched = await _productServices.searchProducts(productName: productName);
notifyListeners();
}
}
//DATABASE TO FIRESTORE
//I tried using stream builder but it is not working using Future.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:farmers_ecommerce/models/product.dart';
class ProductServices {
String collection = "products";
FirebaseFirestore _firestore = FirebaseFirestore.instance;
Future<List<ProductModel>> getProducts() async =>
_firestore.collection(collection).get().then((result) {
List<ProductModel> products = [];
for (DocumentSnapshot product in result.docs) {
products.add(ProductModel.fromSnapshot(product));
}
return products;
});
Future<List<ProductModel>> searchProducts({String productName}) {
// code to convert the first character to uppercase
String searchKey = productName[0].toUpperCase() + productName.substring(1);
return _firestore
.collection(collection). //return fire base
.orderBy("name")
.startAt([searchKey])
.endAt([searchKey + '\uf8ff'])
.get()
.then((result) {
List<ProductModel> products = [];
for (DocumentSnapshot product in result.docs) {
products.add(ProductModel.fromSnapshot(product));
}
return products;
});
}
}
In your ProductServices change this function:
Future<List<ProductModel>> getProducts() async {
QuerySnapshot result= await _firestore.collection(collection).get();
List<ProductModel> products = [];
for (DocumentSnapshot product in result.docs) {
products.add(ProductModel.fromSnapshot(product));
}
return products;
}
If you use then the return will be called when the code flow already left the function. To avoid that you need to await the result.

read number of children from the firebase realtime database using flutter

I'm new to flutter and really need help with my problem regarding reading/calculating the number of children from the firebase real-time database.
The database I use has several categories.
Each category has several cases.
What I want, is to extract the information from the database, how many cases each category has and to show this information in a list. That means - to show the name of the category AND how many children (cases) this category has (totalCases)...
Here is my code, I'm struggling with:
import '../components/category_list_tile.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';
import 'package:flutter/material.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
import '../constants.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_database/firebase_database.dart';
import 'dart:async';
class ScreenCategoryList extends StatefulWidget {
static String id = 'screen_category_list';
final FirebaseApp app;
ScreenCategoryList({this.app});
#override
_ScreenCategoryListState createState() => _ScreenCategoryListState();
}
class _ScreenCategoryListState extends State<ScreenCategoryList> {
final referenceDatabase = FirebaseDatabase.instance;
final _dbRef = FirebaseDatabase.instance.reference().child("de");
static int number = 100;
bool showSpinner = false;
DatabaseReference _databaseReference;
#override
void initState() {
final FirebaseDatabase database = FirebaseDatabase(app: widget.app);
_databaseReference = database.reference().child("de");
super.initState();
}
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.white, Colors.white],
),
image: const DecorationImage(
image: AssetImage("images/background.png"), fit: BoxFit.cover),
),
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
toolbarHeight: 60.0,
elevation: 0.0,
backgroundColor: Colors.black12,
leading: Padding(
padding: EdgeInsets.only(left: 12.0, top: 12.0, bottom: 12.0),
child: Image(image: AssetImage('images/lexlogo_black.png'))),
title: Center(
child: Column(
children: [
Text(
'Kategorien',
style: TextStyle(
color: kMainDarkColor,
fontFamily: 'Roboto',
fontSize: 21.0,
fontWeight: FontWeight.bold),
),
],
),
),
actions: [
Padding(
padding: EdgeInsets.only(right: 8.0),
child: IconButton(
icon: Icon(Icons.more_vert_rounded),
iconSize: 30.0,
color: kMainDarkColor,
onPressed: () {},
//onPressed: onPressMenuButton,
),
),
],
),
body: ModalProgressHUD(
inAsyncCall: showSpinner,
child: FirebaseAnimatedList(
query: _databaseReference.child('category'),
itemBuilder: (
BuildContext context,
DataSnapshot snapshot,
Animation<double> animation,
int index,
) {
Future<int> getNumberOfNodes() async {
final response = await FirebaseDatabase.instance
.reference()
.child('de')
.child('category')
.child('$index')
.child('cases')
.once();
var nodes = [];
response.value.forEach((v) => nodes.add(v));
return nodes.length;
}
var myNumber = getNumberOfNodes();
int myInt = 99;
myNumber.then((value) {
myInt = value;
});
number = myInt;
return CategoryListTile(
title: snapshot.value['name'].toString(),
successfulCases: 1,
totalCases: number,
onTitleClick: () {},
onInfoButtonClick: () {},
);
},
reverse: false,
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
),
),
),
);
}
}
Since you declare Future<int> getNumberOfNodes() async, you need to FutureBuilder to display that value.
Something like this:
child: FutureBuilder<int>(
future: FirebaseDatabase.instance
.reference()
.child('de')
.child('category')
.child('$index')
.child('cases')
.once();
var nodes = [];
response.value.forEach((v) => nodes.add(v));
return nodes.length;
}
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
List<Widget> children;
if (snapshot.hasData) {
return Text("Case count: "+snapshot.data);
} else if (snapshot.hasError) {
return Text('Error: ${snapshot.error}'),
} else {
return CircularProgressIndicator();
}
},
)
I did not compile or run this code, so please treat it as a pseudo-code. If you get any errors while using this, try to fix them by searching for the error message before reporting back.
So the future is the code that determines the value, and then the builder renders the correct UI based on whether the value is available yet. You'll want to replace the Text("Case count: "+snapshot.data) with your own UI, so the CategoryListTile(...).
Thank you #Frank van Puffelen for your suggestion. Finally could read the number of children of at least one category.
The code had to be changed like this:
class _ScreenCategoryListState extends State<ScreenCategoryList> {
final referenceDatabase = FirebaseDatabase.instance;
bool showSpinner = false;
DatabaseReference _databaseReference;
#override
void initState() {
final FirebaseDatabase database = FirebaseDatabase(app: widget.app);
_databaseReference = database.reference().child("de");
super.initState();
}
Future<Map<int, int>> getNumberOfNodes() async {
Map<int, int> caseNumbers = new Map<int, int>();
// read number of category nodes
final categoriesNumbersResponse = await FirebaseDatabase.instance
.reference()
.child('de')
.child('category')
// .child('0')
// .child('cases')
.once();
var categoryNodes = [];
categoriesNumbersResponse.value.forEach((v) => categoryNodes.add(v));
int numberOfCategories = categoryNodes.length;
//read number of cases in category
for (int i = 0; i < numberOfCategories; i++) {
final caseResponse = await FirebaseDatabase.instance
.reference()
.child('de')
.child('category')
.child('$i')
.child('cases')
.once();
var caseNodes = [];
caseResponse.value.forEach((v) => caseNodes.add(v));
int numberOfCases = caseNodes.length;
caseNumbers[i] = numberOfCases;
}
return caseNumbers;
}
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.white, Colors.white],
),
image: const DecorationImage(
image: AssetImage("images/background.png"), fit: BoxFit.cover),
),
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
toolbarHeight: 60.0,
elevation: 0.0,
backgroundColor: Colors.black12,
leading: Padding(
padding: EdgeInsets.only(left: 12.0, top: 12.0, bottom: 12.0),
child: Image(image: AssetImage('images/lexlogo_black.png'))),
title: Center(
child: Column(
children: [
Text(
'Kategorien',
style: TextStyle(
color: kMainDarkColor,
fontFamily: 'Roboto',
fontSize: 21.0,
fontWeight: FontWeight.bold),
),
],
),
),
actions: [
Padding(
padding: EdgeInsets.only(right: 8.0),
child: IconButton(
icon: Icon(Icons.more_vert_rounded),
iconSize: 30.0,
color: kMainDarkColor,
onPressed: () {},
//onPressed: onPressMenuButton,
),
),
],
),
body: FutureBuilder<Map<int, int>>(
future: getNumberOfNodes(),
builder: (BuildContext context,
AsyncSnapshot<Map<int, int>> casesSnapshot) {
if (casesSnapshot.hasData) {
return FirebaseAnimatedList(
reverse: false,
padding: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
query: _databaseReference.child('category'),
itemBuilder: (
BuildContext context,
DataSnapshot categorySnapshot,
Animation<double> animation,
int index,
) {
int numberOfCases = casesSnapshot.data[index];
//print('number of cases $_counter, $numberOfCases');
return CategoryListTile(
title: categorySnapshot.value['name'].toString(),
successfulCases: 10,
totalCases: numberOfCases,
onTitleClick: () {},
onInfoButtonClick: () {},
);
},
);
} else if (casesSnapshot.hasError) {
return Center(
child: Column(
children: <Widget>[
Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Error: ${casesSnapshot.error}'),
)
],
),
);
} else {
return Center(
child: Column(
children: <Widget>[
SizedBox(
child: CircularProgressIndicator(),
width: 60,
height: 60,
),
Padding(
padding: EdgeInsets.only(top: 16),
child: Text('Awaiting result...'),
)
],
),
);
}
},
),
),
);
}
}

How to change element color on Stream Builder Flutter

I have a problem with StreamBuilder. I using FirebaseFirestore and I want to make a quiz app but I don't change my element's color. I used the setState method but it didn't work. How to change element color on Stream Builder?
My codes:
https://paste.tc/dtckRClOTL
import 'package:audioplayers/audio_cache.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:dots_indicator/dots_indicator.dart';
import 'package:exampills/screens/tests/resultScreen.dart';
import 'package:exampills/providers/testProvider.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:random_color/random_color.dart';
class TestScreen extends StatefulWidget {
final String categoryId;
final String subcategoryId;
final String title;
final String testId;
final int questPiece;
const TestScreen(
{Key key,
this.categoryId,
this.subcategoryId,
this.testId,
this.title,
this.questPiece})
: super(key: key);
#override
_TestScreenState createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
int position;
AudioCache audioCache = AudioCache();
AudioPlayer audioPlayer = AudioPlayer();
RandomColor randomColor = RandomColor();
var controller = Get.put(TestProvider());
PageController pageController = PageController();
int testQuestPiece = 0;
Future nextPage() {
pageController.animateToPage(pageController.page.toInt() + 1,
duration: Duration(milliseconds: 400), curve: Curves.easeIn);
}
void previousPage() {
pageController.animateToPage(pageController.page.toInt() - 1,
duration: Duration(milliseconds: 400), curve: Curves.easeIn);
}
getDocs() async {
await FirebaseFirestore.instance
.collection(
"categories/${widget.categoryId}/subcategories/${widget.subcategoryId}/tests/${widget.testId}/questions")
.get()
.then((value) {
setState(() {
testQuestPiece = value.docs.length;
});
});
}
#override
void initState() {
print(controller.position);
controller.updatePosition(0);
getDocs();
super.initState();
}
#override
Widget build(BuildContext context) {
Color color = randomColor.randomColor();
int selectedItem;
bool selectedBool = false;
return Scaffold(
backgroundColor: color,
bottomNavigationBar: Container(
child: DotsIndicator(
dotsCount: testQuestPiece,
position: controller.position,
axis: Axis.horizontal,
reversed: false,
decorator: DotsDecorator(
color: Colors.white,
activeColor: randomColor.randomColor(),
size: const Size.square(9.0),
activeShape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(5.0)),
activeSize: const Size(18.0, 18.0),
),
mainAxisAlignment: MainAxisAlignment.center,
)),
appBar: AppBar(
centerTitle: true,
title: Text(
widget.title,
style: TextStyle(fontWeight: FontWeight.bold),
),
leading: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back_ios),
color: Colors.white,
),
backgroundColor: Colors.transparent,
actions: [
IconButton(
icon: Icon(Icons.timer),
onPressed: () {},
)
]),
body: Stack(
fit: StackFit.expand,
children: [
StreamBuilder(
stream: FirebaseFirestore.instance
.collection(
"categories/${widget.categoryId}/subcategories/${widget.subcategoryId}/tests/${widget.testId}/questions")
.snapshots(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
}
return PageView(
physics: NeverScrollableScrollPhysics(),
allowImplicitScrolling: false,
scrollDirection: Axis.horizontal,
controller: pageController,
onPageChanged: controller.updatePosition,
children: snapshot.data.docs.map<Widget>((data) {
var datas = data.data();
return Stack(
fit: StackFit.expand,
children: [
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 350,
padding: EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(30)),
height: 200,
child: Text(datas['questionTitle'],
style: TextStyle(
color: Colors.black, fontSize: 20))),
SizedBox(
height: 15,
),
Expanded(
child: ListView.builder(
itemCount: datas['answers'].length,
itemBuilder: (context, index) {
return Column(
children: [
InkWell(
onTap: () async {
if (datas['trueAnswer'] == index) {
audioCache
.play("sounds/correct.wav");
} else {
audioCache.play("sounds/wrong.wav");
setState(() {
selectedItem =
datas['trueAnswer'];
selectedBool = true;
});
}
await Future.delayed(
Duration(seconds: 2))
.then((value) {
print(pageController.page.toInt());
print(testQuestPiece);
if ((pageController.page.toInt() +
1) ==
testQuestPiece) {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) =>
ResultScreen()));
} else {
nextPage();
}
});
},
child: Container(
width: 350,
padding: EdgeInsets.all(15),
decoration: BoxDecoration(
color: selectedBool == true
? (selectedItem == index
? Colors.green
: Colors.red)
: Colors.white,
borderRadius:
BorderRadius.circular(30)),
height: 80,
child: Text(
"${index + 1}. " +
datas['answers'][index],
style: TextStyle(
color: Colors.black,
fontSize: 20)),
),
),
SizedBox(
height: 15,
),
],
);
},
),
),
],
),
),
],
);
}).toList(),
);
},
),
],
),
);
}
}

How to get pedometer(stepcountvalue) data on Autoupdate basis from firestore

I want to retrieve StepCountValue from firestore and display it to my app on realtimeAutoupdate basis. RealtimeAutoupdate basis means i want a realtime/without refreshing method.So, if a user cover some distance then he/she gets his/her total walking steps in app.
How to retrieve data from database and throw it in a container(page.dart)
How to get pedometer(stepcountvalue) automatic changing data on Autoupdate and retrieve
With firestore
How to update this data to firestore automatically
This is my main.dart
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter_testing/models/brew.dart';
import 'package:flutter_testing/models/user.dart';
import 'package:flutter_testing/screens/Pages/page.dart';
import 'package:flutter_testing/screens/wrapper.dart';
import 'package:flutter_testing/services/auth.dart';
import 'package:flutter_testing/services/database.dart';
import 'dart:async';
import 'package:percent_indicator/circular_percent_indicator.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:pedometer/pedometer.dart';
import 'package:provider/provider.dart';
void main() => runApp(new NewApp());
class NewApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamProvider<User>.value(
value: AuthService().user,
child: MaterialApp(
home: Wrapper(),
),
);
}
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final AuthService _auth = AuthService();
String muestrePasos = "";
String _km = "Unknown";
String _calories = "Unknown";
String stepCountValue = 'Unknown';
String _showcoin = '0';
StreamSubscription<int> _subscription;
double _numerox; //numero pasos
double _convert;
double _kmx;
double burnedx;
double _coin;
double _porciento;
// double percent=0.1;
#override
void initState() {
super.initState();
//initPlatformState();
setUpPedometer();
}
//inicia codigo pedometer
void setUpPedometer() {
Pedometer pedometer = new Pedometer();
_subscription = pedometer.stepCountStream.listen(_onData,
onError: _onError, onDone: _onDone, cancelOnError: true);
}
void _onData(int stepCountValue1) async {
// print(stepCountValue); //impresion numero pasos por consola
setState(() {
stepCountValue = "$stepCountValue1";
// print(stepCountValue);
});
var dist = stepCountValue1; //pasamos el entero a una variable llamada dist
double y = (dist + .0); //lo convertimos a double una forma de varias
setState(() {
_numerox = y; //lo pasamos a un estado para ser capturado ya convertido a double
});
var long3 = (_numerox);
long3 = num.parse(y.toStringAsFixed(2));
var long4 = (long3 / 10000);
int decimals = 1;
int fac = pow(10, decimals);
double d = long4;
d = (d * fac).round() / fac;
print("d: $d");
getDistanceRun(_numerox);
setState(() {
_convert = d;
print(_convert);
});
}
void reset() {
setState(() {
int stepCountValue1 = 0;
stepCountValue1 = 0;
stepCountValue = "$stepCountValue1";
});
}
void _onDone() {}
void _onError(error) {
print("Flutter Pedometer Error: $error");
}
//function to determine the distance run in kilometers using number of steps
void getDistanceRun(double _numerox) {
var distance = ((_numerox * 76) / 100000);
distance = num.parse(distance.toStringAsFixed(2)); //dos decimales
var distancekmx = distance * 34;
distancekmx = num.parse(distancekmx.toStringAsFixed(2));
//print(distance.runtimeType);
var coiny = ((_numerox * 125) / 100000);
coiny = num.parse(coiny.toStringAsFixed(2));
setState(() {
_km = "$distance";
//print(_km);
});
setState(() {
_kmx = num.parse(distancekmx.toStringAsFixed(2));
});
setState(() {
_coin = num.parse(coiny.toStringAsFixed(2));
//print(_coiny);
});
}
//function to determine the calories burned in kilometers using number of steps
void getBurnedRun() {
setState(() {
var calories = _kmx; //dos decimales
_calories = "$calories";
//print(_calories);
});
}
void coins() {
setState(() {
var showcoin = _coin;
_showcoin = "$showcoin";
});
}
//fin codigo pedometer
#override
Widget build(BuildContext context) {
//print(_stepCountValue);
getBurnedRun();
coins();
return StreamProvider<QuerySnapshot>.value(
value: DatabaseService().step,
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: new Scaffold(
appBar: new AppBar(
title: const Text('Step Counter'),
backgroundColor: Colors.black54,
actions: <Widget>[
FlatButton.icon(
icon: Icon(Icons.person),
label: Text('logout'),
onPressed: () async {
await _auth.signOut();
}
),
FlatButton.icon(
icon: Icon(Icons.arrow_back),
label: Text('New Page'),
onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => pages()));
}
),
],
),
body: new ListView(
padding: EdgeInsets.all(5.0),
children: <Widget>[
Container(
padding: EdgeInsets.only(top: 10.0),
width: 250,
//ancho
height: 250,
//largo tambien por numero height: 300
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment
.bottomCenter, //cambia la iluminacion del degradado
end: Alignment.topCenter,
colors: [Color(0xFFA9F5F2), Color(0xFF01DFD7)],
),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(27.0),
bottomRight: Radius.circular(27.0),
topLeft: Radius.circular(27.0),
topRight: Radius.circular(27.0),
)),
child: new CircularPercentIndicator(
radius: 200.0,
lineWidth: 13.0,
animation: true,
center: Container(
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
height: 50,
width: 50,
padding: EdgeInsets.only(left: 20.0),
child: Icon(
FontAwesomeIcons.walking,
size: 30.0,
color: Colors.white,
),
),
Container(
//color: Colors.orange,
child: Text(
'$stepCountValue',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20.0,
color: Colors.purpleAccent),
),
// height: 50.0,
// width: 50.0,
),
],
),
),
percent: 0.217,
//percent: _convert,
footer: new Text(
"Steps: $stepCountValue",
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 12.0,
color: Colors.purple),
),
circularStrokeCap: CircularStrokeCap.round,
progressColor: Colors.purpleAccent,
),
),
Divider(
height: 5.0,
),
Container(
width: 80,
height: 100,
padding: EdgeInsets.only(left: 25.0, top: 10.0, bottom: 10.0),
color: Colors.transparent,
child: Row(
children: <Widget>[
new Container(
child: new Card(
child: Container(
height: 80.0,
width: 80.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/distance.png"),
fit: BoxFit.fitWidth,
alignment: Alignment.topCenter,
),
),
child: Text(
"$_km Km",
textAlign: TextAlign.right,
style: new TextStyle(
fontWeight: FontWeight.bold, fontSize: 14.0),
),
),
color: Colors.white54,
),
),
VerticalDivider(
width: 20.0,
),
new Container(
child: new Card(
child: Container(
height: 80.0,
width: 80.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/burned.png"),
fit: BoxFit.fitWidth,
alignment: Alignment.topCenter,
),
),
),
color: Colors.transparent,
),
),
VerticalDivider(
width: 20.0,
),
new Container(
child: new Card(
child: Container(
height: 80.0,
width: 80.0,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/step.png"),
fit: BoxFit.fitWidth,
alignment: Alignment.topCenter,
),
),
),
color: Colors.transparent,
),
),
],
),
),
Divider(
height: 2,
),
Container(
padding: EdgeInsets.only(top: 2.0),
width: 150,
//ancho
height: 30,
//largo tambien por numero height: 300
color: Colors.transparent,
child: Row(
children: <Widget>[
new Container(
padding: EdgeInsets.only(left: 40.0),
child: new Card(
child: Container(
child: Text(
"$_km Km",
textAlign: TextAlign.right,
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14.0,
color: Colors.white),
),
),
color: Colors.purple,
),
),
VerticalDivider(
width: 20.0,
),
new Container(
padding: EdgeInsets.only(left: 10.0),
child: new Card(
child: Container(
child: Text(
"$_calories kCal",
textAlign: TextAlign.right,
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14.0,
color: Colors.white),
),
),
color: Colors.red,
),
),
VerticalDivider(
width: 5.0,
),
new Container(
padding: EdgeInsets.only(left: 10.0),
child: new Card(
child: Container(
child: Text(
"$_showcoin Coins",
textAlign: TextAlign.right,
style: new TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14.0,
color: Colors.white),
),
),
color: Colors.black,
),
),
],
),
),
],
),
),
),
);
}
}
this is my wrapper.dart
import 'package:flutter_testing/models/user.dart';
import 'package:flutter_testing/screens/authenticate/authenticate.dart';
import 'package:flutter/material.dart';
import 'package:flutter_testing/main.dart';
import 'package:provider/provider.dart';
class Wrapper extends StatelessWidget {
#override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
// return either the Home or Authenticate widget
if (user == null){
return Authenticate();
} else {
return MyApp();
}
}
}
this is page.dart
import 'package:flutter/material.dart';
import 'package:flutter_testing/main.dart';
class pages extends StatefulWidget {
#override
_pagesState createState() => _pagesState();
}
class _pagesState extends State<pages> {
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.amber,
appBar: new AppBar(
actions: <Widget>[
FlatButton.icon(
icon: Icon(Icons.arrow_back_ios),
label: Text('back'), onPressed: () {
Navigator.of(context)
.push(MaterialPageRoute(builder: (context) => MyApp())
);
}
),
],
),
body: Container(),
);
}
}
this is database.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_testing/models/brew.dart';
class DatabaseService {
final String uid;
DatabaseService({ this.uid });
// collection reference
final CollectionReference brewCollection = Firestore.instance.collection('step');
Future<void> updateUserData(int stepCountValue, int _calories, int _km , int _showcoin) async {
return await brewCollection.document(uid).setData({
'stepCountValue': stepCountValue,
'_calories': _calories,
'_km': _km,
'_showcoin': _showcoin,
});
// get brews stream
Stream<QuerySnapshot> get step {
return brewCollection.snapshots();
}
}
this is brew.dart
class Brew {
final int stepCountValue;
Brew({ this.stepCountValue });
}
I hope this is enough to solve my problem. I'm very new to Flutter and I dont know much about firebase and firestore, so it would be nice, if you can say where EXACTLY I have to change WHAT or add WHAT. Thank you so much!!!
You can write a query in the _onData() function of your main.dart file this will update the data automatically whenever there will be any change in your steps. And you can retrieve data in real time using streamBuilder easily.
for example:
void _onData(int stepCountValue1) async {
// print(stepCountValue); //impresion numero pasos por consola
setState(() {
stepCountValue = "$stepCountValue1";
});
final CollectionReference brewCollection = Firestore.instance.collection('step');
await brewCollection.document(uid).setData({
'stepCountValue': stepCountValue,
});
}

Flutter: Hide or Display Child Widget using an Expression from Boolean values from firebase firestore

I have been trying to set a boolean expression to show or hide a text widget, by getting the true or false statement from the firebase. Here is the code and what i have tried. The firebase line reads Product On-Sale: true (boolean).
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
// import 'package:productScreen.dart';
// import 'package:resources/app_data.dart';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder(
stream: Firestore.instance.collection(appProducts).snapshots(),
// ignore: missing_return
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).primaryColor)));
} else {
final int dataCount = snapshot.data.documents.length;
print("data count $dataCount");
if (dataCount == 0) {
print('No data Available');
} else {
return CustomScrollView(
slivers: <Widget>[
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
childAspectRatio: 0.6,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
final DocumentSnapshot document =
snapshot.data.documents[index];
return buildProducts(context, index, document);
},
childCount: dataCount,
),
),
],
);
}
}
}),
);
}
}
// import 'package:pages/productScreen.dart';
class NewProductScreen extends StatefulWidget {
final String productImage, productTitle, productPrice, productSales;
final bool productOnSale;
const NewProductScreen(
{Key key,
this.productImage,
this.productTitle,
this.productPrice,
this.productSales,
this.productOnSale})
: super(key: key);
#override
_NewProductScreenState createState() => _NewProductScreenState();
}
int indicatorActive = 0;
int _currentIndex = 0;
int selectedSizeIndex = 0;
int selectedColorIndex = 0;
class _NewProductScreenState extends State<NewProductScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder(
stream: Firestore.instance.collection(appProducts).snapshots(),
// ignore: missing_return
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).primaryColor)));
} else {
final int dataCount = snapshot.data.documents.length;
print("data count $dataCount");
if (dataCount == 0) {
print('No data Available');
} else {
return CustomScrollView(
slivers: <Widget>[
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
childAspectRatio: 0.6,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
final DocumentSnapshot document =
snapshot.data.documents[index];
return buildProducts(context, index, document);
},
childCount: dataCount,
),
)
],
);
}
}
}));
}
}
Widget buildProducts(
BuildContext context, int index, DocumentSnapshot document) {
List productImage = document[pImages] as List;
bool onSales = document[pOnSale];
onSales = false;
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NewProductScreen(
productImage: document[pImages],
productTitle: document[pTitle],
productSales: document[pSalesPrice],
productPrice: document[pPrice],
productOnSale: document[pOnSale],
)));
},
child: Card(
elevation: 3,
child: ClipRRect(
borderRadius: BorderRadius.circular(5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height / 3.5,
width: MediaQuery.of(context).size.width / 2,
decoration: BoxDecoration(
image: DecorationImage(image: NetworkImage(productImage[0]))),
),
Expanded(
flex: 1,
child: Center(
child: Container(
padding: EdgeInsets.only(top: 5),
height: MediaQuery.of(context).size.height / 10,
child: Text(
"${document[pTitle]}",
style: TextStyle(
color: Colors.black,
fontSize: 15,
fontWeight: FontWeight.normal,
),
),
),
),
),
Expanded(
flex: 1,
child: Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
Padding(
padding: const EdgeInsets.only(left: 8),
child: Text(
"\₦${document[pPrice]}",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.normal,
color: const Color(0xfff08804),
),
),
),
SizedBox(
height: 5,
),
Text(
onSales ? "On Sale" : "",
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.normal,
color: Colors.grey,
),
),
],
),
),
),
],
),
),
),
);
}
// import 'package:resources/app_data.dart';
const String appProducts = "appProducts";
const String pTitle = "Product Title";
const String pPrice = "Product Price";
const String pSalesPrice = "Product Sales Price";
const String pImages = "Product Images";
const String pOnSale = "Product OnSale";
So therefore, i want to use a true or false expression to get the text widget to display text or an empty text
onSales ? "On Sale" : "",
![1]: https://imgur.com/bI9QGDx "firebase image as requested"
since your onSales = false; here is false its giving expected result, to get bool from firestore from your code do this get bool value
document['yourboolkey']
then
Text(
document['yourboolkey'] ? "On Sale" : "",
style: TextStyle(
fontSize: 10,...
I was able to solve the problem by creating a product Model and using "Providers" to manage the state.
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider.value(value: ProductProvider.initialize()),
StreamProvider.value(value: AuthService().user,)
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: "On Sale",
theme: ThemeData(
scaffoldBackgroundColor: BGColor,
accentColor: Colors.white70,
// home: Wrapper(),
routes: {
'/': (context) => Wrapper(),
},
// screens.home: Home(),
),
);
}
}
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
final productProvider = Provider.of<ProductProvider>(context);
return Scaffold(
appBar: buildGradientAppBar(),
body: CustomScrollView(
slivers: <Widget>[
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
childAspectRatio: 0.6,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return ProductGridCard(product: productProvider.products[index]);
},
childCount: productProvider.products.length,
),
),
],
)
);
}
}
class ProductGridCard extends StatelessWidget {
final ProductModel product;
const ProductGridCard({Key key, this.product}) : super(key: key);
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NewProductScreen(
)));
},
child: Card(
elevation: 3,
child: ClipRRect(
borderRadius: BorderRadius.circular(5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
height: MediaQuery.of(context).size.height / 3.5,
width: MediaQuery.of(context).size.width / 2,
decoration: BoxDecoration(
image: DecorationImage(image: NetworkImage(product.images[0]))),
),
Expanded(
flex: 1,
child: Center(
child: Container(
padding: EdgeInsets.only(top: 5),
height: MediaQuery.of(context).size.height / 10,
child: Text(
"${product.title}",
style: TextStyle(
color: Colors.black,
fontSize: 15,
fontWeight: FontWeight.normal,
),
),
),
),
),
Expanded(
flex: 1,
child: Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: [
Padding(
padding: const EdgeInsets.only(left: 8),
child: Text(
"\₦${product.price}",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.normal,
color: const Color(0xfff08804),
),
),
),
SizedBox(
height: 5,
),
Padding(
padding: const EdgeInsets.only(left: 8),
child: Text(
"${product.price}",
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.normal,
color: Colors.grey,
),
),
),
SizedBox(
width: 15,
),
Text(
product.onSale ? 'ON SALE ' : "",
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.normal,
color: Colors.grey,
),
),
],
),
),
),
],
),
),
),
);
}
}
class ProductServices {
String collection = "appProducts";
Firestore _firestore = Firestore.instance;
Future<List<ProductModel>> getProducts() async =>
_firestore.collection(collection).getDocuments().then((result) {
List<ProductModel> products = [];
for (DocumentSnapshot product in result.documents) {
products.add(ProductModel.fromSnapshot(product));
}
return products;
});
}
class ProductProvider with ChangeNotifier{
ProductServices _productServices = ProductServices();
List<ProductModel> products = [];
// List<ProductModel> productsSearched = [];
ProductProvider.initialize(){
loadProducts();
}
loadProducts()async{
products = await _productServices.getProducts();
notifyListeners();
}
}
class ProductModel{
static const ID = "id";
static const TITLE = "Product Title";
static const Images = "Product Images";
static const PRICE = "Product Price";
static const SALE = "Product On-Sale";
String _id;
String _title;
List _images;
String _price;
bool _onSale;
String get id => _id;
String get title => _title;
List get images => _images;
String get price => _price;
bool get onSale => _onSale;
ProductModel.fromSnapshot(DocumentSnapshot snapshot) {
// _id = snapshot.data()[ID];
_onSale = snapshot.data[SALE];
_price = snapshot.data[PRICE];
_title = snapshot.data[TITLE];
_images = snapshot.data[Images];
}
}```
Without the product model, the boolean won't be able to get the value of the boolean from firebase.
`bool get onSale => _onSale;`

Resources