Flutter setState list isnt updating Listviewbuilder - flutter

I have a simple list and I am filter the list by date range picker. All is working fine its showing result also that list is filter success but on ListView builer its showing this error.
Class 'WhereIterable<Object>' has no instance method '[]'.
My code
Future<List> getCustomerList() async {
print(widget.data);
// print('check running');
final storage = new FlutterSecureStorage();
String uUid = await storage.read(key: "uUid");
CollectionReference _collectionRef =
FirebaseFirestore.instance.collection('Transaction');
QuerySnapshot querySnapshot = await _collectionRef.get();
// Get data from docs and convert map to List
List allData = querySnapshot.docs
.where((element) => element['CustomerID'] == widget.data['customerID'])
.map((doc) => doc.data())
.toList();
print(allData);
restore = allData;
backrestore = allData;
setState(() {
show = true;
});
}
Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () async {
final List<DateTime> picked =
await DateRangePicker.showDatePicker(
context: context,
initialFirstDate: new DateTime.now(),
initialLastDate: (new DateTime.now())
.add(new Duration(days: 6)),
firstDate: new DateTime(2015),
lastDate:
new DateTime(DateTime.now().year + 2));
if (picked != null && picked.length == 2) {
print(picked);
selectedDate = picked[0];
DateTime endDate = picked[1];
List<DateTime> days = [];
var filterData = backrestore;
DateTime date = DateTime.parse(
filterData[0]['lastupdate'].toDate().toString());
print(date);
for (int i = 0;
i <= endDate.difference(selectedDate).inDays;
i++) {
days.add(selectedDate.add(Duration(days: i)));
}
print(days);
final filteredItemsToAdd = filterData.where((item) =>
days.contains(DateTime.parse(
item['lastupdate'].toDate().toString())));
print(filteredItemsToAdd.length);
print(filteredItemsToAdd);
setState(() {
restore = filteredItemsToAdd;
});
}
},
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Color(0xffE5E7E9)
),child: Padding(
padding: const EdgeInsets.all(13.0),
child: Text('Date'),
))),
),
Container(
height: Height * 0.5,
child: ListView.builder(
shrinkWrap: true,
itemCount: restore.length,
itemBuilder: (BuildContext context, int index) {
DateTime date = DateTime.parse(
restore[index]['lastupdate'].toDate().toString());
// print(DateFormat('dd-MMM-yyy').format(date)); // prints 2019-04-16
// print('List length ${snapshot.data.length}');
return Padding(
padding: const EdgeInsets.only(left: 13, right: 13),
child: Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(color: Colors.grey, width: .5)),
),
child: Padding(
padding: const EdgeInsets.all(13.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
DateFormat('dd MMM yyy').format(date).toString(),
style: TextStyle(fontFamily: 'PoppinsMedium'),
),
Row(
children: [
Text(
restore[index]['give'].toString(),
style: TextStyle(
fontFamily: 'PoppinsMedium',
color: Colors.green),
),
SizedBox(
width: 60,
),
Text(
restore[index]['take'].toString(),
style: TextStyle(
fontFamily: 'PoppinsMedium',
color: Colors.red),
),
],
)
],
),
),
),
);
},
),
),
You can see I am fetching list then saving on object. And on DateRange picker I am changing the new value by setState but dont know why its showing this error.

I believe this code causes the problem
List allData = querySnapshot.docs
.where((element) => element['CustomerID'] == widget.data['customerID'])
.map((doc) => doc.data())
.toList();
element has type QueryDocumentSnapshot. Replace element['CustomerID'] by element.data()['customID'].

Related

How to Fetching data from sql database in flutter between two date?

in flutter and sqflite i created this function to calculate the total of price in colPrix.
I want to calculate total prices between two dates (period time) by pick and choose the date of start and the end date every time want to calculate the total .
What shoud i do ?
1/function calculate Total in database (where i create database).
class DatabaseHelper {
static DatabaseHelper _databaseHelper; // Singleton DatabaseHelper
static Database _database; // Singleton Database
String clientTable = 'client_table';
String colId = 'id';
String colNumerotelephone = 'numerotelephone';
String colCode = 'code';
String colPrix = 'prix';
String colPriority = 'priority';
String colColor = 'color';
String colDate = 'date';
DatabaseHelper._createInstance();
factory DatabaseHelper() {
if (_databaseHelper == null) {_databaseHelper = DatabaseHelper._createInstance(); // This is executed only once, singleton object}
return _databaseHelper;
}
Future<Database> get database async {
if (_database == null) { _database = await initializeDatabase();}
return _database;
}
.....
.....
Future claculTotalPeriod (String startDate, String endDate) async {
var totalClientperiod = await database;
var result = await totalClientperiod.rawQuery("SELECT SUM($colPrix) AS TOTAL from $clientTable WHERE $colDate BETWEEN '$startDate' AND '$endDate'");
return result.toList();
}
}
2/display the result
class ClientList extends StatefulWidget {
const ClientList({Key key}) : super(key: key);
#override
State<StatefulWidget> createState() {
return ClientListState();
}
}
class ClientListState extends State<ClientList> {
DatabaseHelper databaseHelper = DatabaseHelper();
List<Client> clientList;
int count = 0;
int axisCount = 2;
double somme_period = 00;
String somme_total_period = "00.00";
String startDate='';
String endDate='';
TextEditingController startdate = TextEditingController();
TextEditingController finishdate = TextEditingController();
void calcul_total_period() async {
var total_sum_period = (await databaseHelper.claculTotalPeriod(startDate, endDate))[0]['$startDate''$endDate'];
setState(() {
somme_period = total_sum_period ?? 00;
somme_total_period = somme.toStringAsFixed(2);
});
}
#override
Widget build(BuildContext context) {
if (clientList == null) {
clientList = [];
updateListView();
}
return Scaffold(
appBar: myAppBar(),
body: clientList.isEmpty
? Container(
color: Colors.white,
child: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text('add+',
style: Theme.of(context).textTheme.bodyText2),
),
),
)
: Container(
color: Colors.white,
child: getClientsList(),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
navigateToDetail(Client('', '', '', 3, 0, 0.0), 'new');
},
tooltip: 'add',
shape: const CircleBorder(
side: BorderSide(color: Colors.black, width: 2.0)),
child: const Icon(Icons.add, color: Colors.black),
backgroundColor: Colors.white,
),
bottomNavigationBar: OutlinedButton(
onPressed: () {
showDialog(
...
child: Column(
TextField(
controller: startdate,
decoration: const InputDecoration(
icon: Icon(Icons.calendar_today
),
onTap: () async {
DateTime pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2022,12),
lastDate: DateTime(2026,12));
if (pickedDate != null) {
print(
pickedDate);
String formattedDate =
DateFormat('yyyy-MM-dd').format(pickedDate);
print(
formattedDate); //formatted date output using intl package => 2021-03-16
setState(() {
startdate.text =
formattedDate;
startDate = startdate.text.toString();
});
} else {}
},
),
const SizedBox(height: 20,),
TextField(
controller: finishdate,
decoration: const InputDecoration(
icon: Icon(Icons.calendar_today), //icon of text field
),
onTap: () async {
DateTime pickedDate = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2022,12),
lastDate: DateTime(2026,12));
if (pickedDate != null) {
print(
pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000
String formattedDate =
DateFormat('yyyy-MM-dd').format(pickedDate);
print(
formattedDate); //formatted date output using intl package => 2021-03-16
setState(() {
finishdate.text =
formattedDate; //set output date to TextField value.
endDate = finishdate.text.toString();
});
} else {}
},
),
const SizedBox(height: 20,),
OutlinedButton(
onPressed: () {
calcul_total_period();
},
child: const Text(' total in period')),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
somme_total_period,
style: Theme.of(context).textTheme.headline5,
textAlign: TextAlign.center,
),
),
],
),
),
);
});
},
child: const Text('total')),
);
}
Widget getClientsList() {
return StaggeredGridView.countBuilder(
physics: const BouncingScrollPhysics(),
crossAxisCount: 4,
itemCount: count,
itemBuilder: (BuildContext context, int index) => GestureDetector(
onTap: () {
navigateToDetail(clientList[index], 'edit');
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: colors[clientList[index].color],
border: Border.all(width: 2, color: Colors.black),
borderRadius: BorderRadius.circular(8.0)),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
clientList[index].numerotelephone,
style: Theme.of(context).textTheme.bodyText2,
),
),
),
Text(
getPriorityText(clientList[index].priority),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
clientList[index].code,
style: Theme.of(context).textTheme.bodyText2,
),
),
),
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: Text(clientList[index].prix.toString() ?? 0,
style: Theme.of(context).textTheme.bodyText1),
)
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(clientList[index].date,
style: Theme.of(context).textTheme.subtitle2),
])
],
),
),
),
),
staggeredTileBuilder: (int index) => StaggeredTile.fit(axisCount),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
);
}
void navigateToDetail(Client client, String title) async {
bool result = await Navigator.push(context,
MaterialPageRoute(builder: (context) => ClientDetail(client, title)));
if (result == true) {
updateListView();
}
}
void updateListView() {
final Future<Database> dbFuture = databaseHelper.initializeDatabase();
dbFuture.then((database) {
Future<List<Client>> clientListFuture = databaseHelper.getClientList();
clientListFuture.then((clientList) {
setState(() {
this.clientList = clientList;
count = clientList.length;
});
});
});
}
}
You can do like this
List<Map> results = await dbClient.rawQuery(
"SELECT SUM(col) as TOTAL "
"FROM MyTable "
"AND dateTimeStamp >= ? "
"AND dateTimeStamp <= ? "
"ORDER BY dateTimeStamp ASC ",
[fromTimestamp,toTimeStamp]);

How to calculate age from datepicker using flutter?

In my code I used datepicker to selcte birthday .In date picker has a rang.And when the user select birthday and close the app and reopen later then also display that selected birthday.For that I used sharedprefernces , I want calculate age from birthday when the user select birthday then should automatically calculate age.
Image of UI
package
code
import 'package:age_calculator/age_calculator.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class BirthdayScreen extends StatefulWidget {
const BirthdayScreen({Key? key}) : super(key: key);
#override
State<BirthdayScreen> createState() => _BirthdayScreenState();
}
class _BirthdayScreenState extends State<BirthdayScreen> {
// 1st dropdown button
#override
void initState() {
super.initState();
dropdownValueBirthday = birthday.first;
checkValueBirthday();
}
//date picker
DateTime? selectedDate;
DateTime now = new DateTime.now();
void showDatePicker() {
DateTime mindate = DateTime(now.year - 2, now.month, now.day - 29);
DateTime maxdate = DateTime(now.year - 1, now.month, now.day);
showCupertinoModalPopup(
context: context,
builder: (BuildContext builder) {
return Container(
height: MediaQuery.of(context).copyWith().size.height * 0.25,
color: Colors.white,
child: CupertinoDatePicker(
mode: CupertinoDatePickerMode.date,
initialDateTime: mindate,
onDateTimeChanged: (value) {
if (value != selectedDate) {
setState(() {
selectedDate = value;
dropdownValueBirthday =
'${selectedDate?.year}/${selectedDate?.month}/${selectedDate?.day} ';
calAge();
});
}
},
maximumDate: maxdate,
minimumDate: mindate,
),
);
});
}
String? dropdownValueBirthday;
List<String> birthday = [
'Birthday',
];
//IF "dropdownValueMembers" is empty pass "which" word as a initial value if al ready selected then pass the shared preference value
checkValueBirthday() {
_getDataBirthday();
}
_saveDataBirthday(String dropdownValueBirthdayShared) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString("dataBirthday", dropdownValueBirthdayShared);
}
_getDataBirthday() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
dropdownValueBirthday =
sharedPreferences.getString("dataBirthday") ?? birthday.first;
setState(() {});
}
String age = "";
DateDuration? duration;
getAge(DateTime fromDate) =>
DateTime.now().difference(fromDate).inDays ~/ 365;
void calAge() {
// DateTime birthday = DateTime.parse(dropdownValueBirthday!);
//
// setState(() {
// duration = AgeCalculator.age(birthday);
// });
DateTime? birt; // DateTime(1990);
if (birt != null) {
print('age from birt: ${getAge(birt)}');
} else {
print('birt is null');
}
}
#override
Widget build(BuildContext context) {
print(duration);
print(dropdownValueBirthday);
return Scaffold(
body: Container(
child: Column(
children: [
Center(
child: Padding(
padding: const EdgeInsets.only(left: 15, top: 100),
child: Row(
children: <Widget>[
const Icon(
Icons.brightness_1,
color: Colors.black,
size: 10,
),
const Padding(
padding: EdgeInsets.only(left: 15.0),
child: Text("birthday",
style: TextStyle(
fontSize: 16.0,
)),
),
Padding(
padding: const EdgeInsets.only(left: 25.0),
child: SizedBox(
width: 110.0,
height: 25.0,
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.white,
),
child: Center(
child: Text(
selectedDate == null
? (dropdownValueBirthday ?? birthday.first)
: '${selectedDate?.year}/${selectedDate?.month}/${selectedDate?.day} ',
style: const TextStyle(
fontSize: 16, fontWeight: FontWeight.w500),
),
),
),
),
),
Padding(
padding: const EdgeInsets.only(left: 15.0, top: 30.0),
child: SizedBox(
width: 88.0,
height: 25.0,
child: MaterialButton(
onPressed: showDatePicker,
shape: const StadiumBorder(),
color: Colors.blue,
child: const Text(
'select',
style: TextStyle(color: Colors.white, fontSize: 12),
),
),
),
),
],
),
),
),
Padding(
padding: const EdgeInsets.only(
bottom: 0.0,
),
child: SizedBox(
width: 160.0,
height: 35.0,
child: ElevatedButton(
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: const BorderSide(
color: Colors.blueAccent,
),
),
),
),
onPressed: () {
_saveDataBirthday(dropdownValueBirthday!);
// _saveDataAgree(isChecked!);
},
child: const Text('next')),
),
),
],
),
),
);
}
}
now display this
if (value != selectedDate) {
setState(() {
selectedDate = value;
if(value != null){
birt = DateTime.now().difference(value).inDays ~/ 365;
}
dropdownValueBirthday =
'${selectedDate?.year}/${selectedDate?.month}/${selectedDate?.day} ';
calAge();
});
and decalre the birt at the top Datetime? birt;
void calAge() {
// DateTime birthday = DateTime.parse(dropdownValueBirthday!);
//
// setState(() {
// duration = AgeCalculator.age(birthday);
// });
if (birt != null) {
print('age from birt: ${getAge(birt)}');
} else {
print('birt is null');
}
}
I haven't counted leap years but for me is acceptable.
/*
getAge(DateTime fromDate) => DateTime.now().difference(fromDate).inDays ~/ 365;
void main() {
DateTime? birt; // DateTime(1996);
if(birt != null){
print('age from birt: ${getAge(birt)}');
}else{
print('birt is null');
}
}
*/
getAge(DateTime? fromDate) => fromDate != null ? DateTime.now().difference(fromDate).inDays ~/ 365 : null;
void main() {
print('getAge result: ${getAge(null)}'); // getAge result: null
print('getAge result: ${getAge(DateTime(1990))}'); // getAge result: 32
print('getAge result: ${getAge(DateTime(2020))}'); // getAge result: 2
}

Why is clearing a List using setState not working for clearing my ListView as well?

I have the following code for populating a list which I use for a ListView
List<dynamic> menuItemList =[];
Future<void> displayItems() async {
// I recently tried setState here after trying it onTap() of menu option
setState(() {
menuItemList.clear();
});
var getMenuIDs =
await _dbRef.child('Categories/$categoryPath').onValue.listen((event) {
if (event.snapshot.value != null) {
//fetching all available records in orderTracker
var data = event.snapshot.value as Map;
//adding records to list
data.entries.map((e) => itemIDList.add(e.value)).toList();
//cycling through the list and extracting the orderID
var listLength = itemIDList.length;
for (var i = 0; i < listLength; i++) {
var listItem = itemIDList[i].toString();
itemID = listItem.substring(9, 12);
// trackerID = listItem.substring(12, 15);
allMenuDetail(itemID);
}
} else {
//Empty
}
});
}
Future<void> allMenuDetail(String itemID) async {
//List will be empty here
_streamSubscriber =
await _dbRef.child('MenuItem/$itemID').onValue.listen((event) {
//For some reason it repopulates here
if (event.snapshot.value != null) {
var data = event.snapshot.value as Map;
var price = data['price'];
var itemName = data['itemName'];
var desc = data['description'];
var itemImg = data['img'];
var item = data['id'];
Map<String, dynamic> myMap = {
'price': price,
'itemName': itemName,
'desc': desc,
'img': itemImg,
'itemID': itemID
};
List<dynamic> shortList = [myMap];
menuItemList.addAll(shortList);
setState(() {});
} else {
print('*********************=> HERE ');
}
});
}
I then display the menu item as follows:
ListView.builder(
itemCount: menuItemList.length,
itemBuilder: (context, index) {
final item = menuItemList[index];
var price = item['price'];
var itemName = item['itemName'];
var desc = item['desc'];
var itemImg = item['img'];
var itemID = item['itemID'];
return InkWell(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => ItemPageState(
// path: categoryPath,
itemName: itemName,
desc: desc,
price: price,
itemImg: itemImg,
id: itemID)));
},
child: Card(
color: Colors.white,
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ClipRect(
child: Align(
alignment: Alignment.center,
widthFactor: 0.8,
child: Image(
image: AssetImage(itemImg),
height: 100,
width: 150,
fit: BoxFit.cover,
),
)),
const SizedBox(width: 30),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
itemName,
style: const TextStyle(
color: Colors.black, fontSize: 25),
),
Text(
'Price: R' +
price.toString(), //+ price.toString(),
style: const TextStyle(
color: Colors.black, fontSize: 18),
),
],
),
const SizedBox(width: 30),
]),
));
},
)
I have a menu at the top of my page which will used to navigate to different categories of food. Once one of the icons is clicked I am able to fetch the relevant menu items but the list doesn't clear properly. I have use prints and it says the list has been emptied but on the GUI it just adds the other menu items at the bottom of the one first loaded
this is my menu code
Container(
height: 100,
child: ListView.separated(
padding: EdgeInsets.all(10),
separatorBuilder: (context, _) => const SizedBox(
width: 12,
),
scrollDirection: Axis.horizontal,
itemCount: categoryMenuList.length,
itemBuilder: (context, index) {
final catItem = categoryMenuList[index];
var catIgm = catItem['img'];
var title = catItem['title'];
var path = catItem['path'];
return Container(
width: 95,
height: 100,
child: Column(
children: [
Expanded(
child: AspectRatio(
aspectRatio: 4 / 3,
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Material(
child: Ink.image(
image: AssetImage(catIgm),
fit: BoxFit.cover,
child: InkWell(
onTap: () {
//I did try set state here as well
categoryPath = path;
pageTitle = title;
displayItems();
setState(() {});
refreshPage();
},
),
))))),
const SizedBox(
height: 4,
),
Text(
title,
style: const TextStyle(
color: Colors.black, fontSize: 20),
)
],
),
);
}),
),
Sorry for the long winded post but I can't figure out where I'm going wrong

I am having trouble iterating through an array of objects

I am trying to go through an array of objects, I stored them in my SharedPreferences where I go the data from firebase and add the quantity for each object, now I only want to display the title, price, and quantity of the product in the cart. I was able to pull all the values belonging to the product to the cart screen but how to loop through the nested values in the cart screen is the problem. please can anyone help me still learning more on flutter?
Cart screen
#override
Widget build(BuildContext context) {
SharedPreferences prefs = SharedPreferences.getInstance() as SharedPreferences;
var cart = prefs.getStringList('userCart');
return Row(
children: [
SizedBox(
width: getProportionateScreenWidth(88),
child: AspectRatio(
aspectRatio: 0.88,
child: Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Color(0XFFF5F6F9),
borderRadius: BorderRadius.circular(15),
),
child: Image.network(cart![0]),
// child: Image.network(cart.product.images[0]),
),
),
),
SizedBox(
width: getProportionateScreenWidth(20),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
cart.first,
// cart.product.title,
style: TextStyle(fontSize: 16, color: Colors.black),
maxLines: 2,
),
const SizedBox(
height: 10,
),
Text.rich(
TextSpan(
text: "\$${cart.product.price}",
style: TextStyle(
color: kPrimaryColor,
),
children: [
TextSpan(
text: " x${cart.numOfItem}",
style: TextStyle(
color: kTextColor,
),
),
],
),
),
],
)
],
);
}
Storing the data from firebase and adding quantity
Future<void> checkItemInCart(
Product product, int quantity, BuildContext context) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
// convert to map
var product_str = product.toMap();
// combine product with quantity
String productWithQuantity =
product_str.toString() + '-quantity-' + quantity.toString();
// check if project exists first
List<String> userCartPref = (prefs.getStringList('userCart') ?? <String>[]);
['Product-quantity-2'];
/*
update {
check if found
}
*/
List<String> temp = (prefs.getStringList('userCart') ?? <String>[]);
// add f
//userCartPref ['iphone 1','laptop 3'];
// temp ['laptop 3'];
var foundInCart = false;
for (var i = 0; i < userCartPref.length; i++) {
var item = userCartPref[i];
var items = item.split('-quantity-'); //list [product,quantity]
var old_product = items[0];
var old_qty = items[1];
if (old_product.contains(product.pid)) {
foundInCart = true;
// product exists
// delete the current item
temp.removeAt(i);
// set pref to temp
prefs.setStringList('userCart', temp);
// sum the quantity 2 1
String finalQuantity = (quantity + int.parse(old_qty)).toString();
// create string for pref with the updated quantity
String updatedProductWithQuantity =
product_str.toString() + '-quantity-' + finalQuantity;
//add item with the updated quantity iphone 2
addItemToCart(updatedProductWithQuantity, context);
showSnackBar(context, "Quantity has been updated successfully");
break;
}
}
if (userCartPref.length == 0 || foundInCart == false) {
addItemToCart(productWithQuantity, context);
showSnackBar(context, "Product added successfully to cart");
}
await getProducts();
}
Future<void> addItemToCart(String product, BuildContext context) async {
// await clearPref();
print("inside");
SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> tempCartList = (prefs.getStringList('userCart') ?? <String>[]);
// print(tempCartList);
tempCartList.add(product);
prefs.setStringList('userCart', tempCartList);
}
Future<void> getProducts() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
List<String> tempCartList =
(preferences.getStringList('userCart') ?? <String>[]);
for (var i = 0; i < tempCartList.length; i++) {
var item = tempCartList[i];
var items = item.split('-quantity-');
var product_ = items[0];
var quantity_ = items[1];
}
}
you can use ListView.builder or GridView.builder to iterate over the array and render them on screen. So if I use ListView.builder, my code in cart screen would look like:
return ListView.builder(
itemCount: cart.length, //length of cart
itemBuilder: (context, index) {
return Row(
children: [
SizedBox(
width: getProportionateScreenWidth(88),
child: AspectRatio(
aspectRatio: 0.88,
child: Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Color(0XFFF5F6F9),
borderRadius: BorderRadius.circular(15),
),
child: Image.network(cart![index]),
// child: Image.network(cart.product.images[0]),
),
),
),
SizedBox(
width: getProportionateScreenWidth(20),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
cart[index].product.title,
// cart.product.title,
style: TextStyle(fontSize: 16, color: Colors.black),
maxLines: 2,
),
const SizedBox(
height: 10,
),
Text.rich(
TextSpan(
text: "\$${cart[index].product.price}",
style: TextStyle(
color: kPrimaryColor,
),
children: [
TextSpan(
text: " x${cart[index].numOfItem}",
style: TextStyle(
color: kTextColor,
),
),
],
),
),
],
)
],
);
},
);

Flutter FutureBuilder calling function continuously

I have simple function which is calling data from firestore and filtering data. But issue is my futurebuilder keeps on loader situation (Data is called successfully i can see in console but now showing in future) I think its because my fucntion is calling in loop or something i have try to print something in my function which indicates me that my function is not stopping and thats why i think my futureBuilder keeps on loading.
My code
Future<List> getCustomerList() async {
print('calling');
String uUid1 = await storage.read(key: "uUid");
String uName1 = await storage.read(key: "uName");
String uNumber1 = await storage.read(key: "uNumber");
setState(() {
uUid = uUid1;
uName = uName1;
uNumber = uNumber1;
});
CollectionReference _collectionRef =
FirebaseFirestore.instance.collection('Customers');
QuerySnapshot querySnapshot = await _collectionRef.get();
// Get data from docs and convert map to List
List allData = querySnapshot.docs
.where((element) => element['sellerUID'] == uUid)
.map((doc) => doc.data())
.toList();
double gGive = 0;
double gTake = 0;
double gCal = 0;
for (int i = 0; i < allData.length; i++) {
// print(allData[i]);
// print('give ${double.parse(allData[i]['give'].toString()) }');
// print('take ${double.parse(allData[i]['take'].toString()) }');
double.parse(allData[i]['give'].toString()) -
double.parse(allData[i]['take'].toString()) >
0
? gGive += double.parse(allData[i]['give'].toString()) -
double.parse(allData[i]['take'].toString())
: gTake += double.parse(allData[i]['give'].toString()) -
double.parse(allData[i]['take'].toString());
}
// print(gGive);
// print(gTake);
setState(() {
Gtake = gGive.toString().replaceAll("-", "");
Ggive = gTake.toString().replaceAll("-", "");
});
if (greenBox) {
var check = allData.where((i) => i['take'] > i['give']).toList();
return check;
} else if (redBox) {
var check = allData.where((i) => i['give'] > 1).toList();
return check;
} else {
return allData;
}
}
And my futureBuilder look like this
Expanded(
child: Container(
height: Height * 0.5,
child: FutureBuilder(
future: getCustomerList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
list = snapshot.data;
return SingleChildScrollView(
child: Column(
children: [
Container(
height: Height * 0.5,
child: ListView.builder(
shrinkWrap: true,
itemCount: list.length,
itemBuilder:
(BuildContext context,
int index) {
var showThis = list[index]
['give'] -
list[index]['take'];
return list[index]
['customerName']
.toString()
.contains(searchString)
? GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
CustomerData(
data: list[
index])),
);
},
child: Padding(
padding:
const EdgeInsets
.only(
left: 13,
right: 13),
child: Container(
decoration:
BoxDecoration(
border: Border(
top: BorderSide(
color: Colors
.grey,
width:
.5)),
),
child: Padding(
padding:
const EdgeInsets
.all(
13.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Row(
children: [
CircleAvatar(
child:
Text(
list[index]['customerName'][0]
.toString(),
style:
TextStyle(fontFamily: 'PoppinsBold'),
),
backgroundColor:
Color(0xffF7F9F9),
),
SizedBox(
width:
20,
),
Text(
list[index]['customerName']
.toString(),
style: TextStyle(
fontFamily:
'PoppinsMedium'),
),
],
),
Text(
'RS ${showThis.toString().replaceAll("-", "")}',
style: TextStyle(
fontFamily:
'PoppinsMedium',
color: list[index]['give'] - list[index]['take'] <
0
? Colors.green
: Colors.red),
),
],
),
),
),
),
)
: Container();
},
),
)
],
),
);
} else
return Center(
heightFactor: 1,
widthFactor: 1,
child: SizedBox(
height: 70,
width: 70,
child: CircularProgressIndicator(
strokeWidth: 2.5,
),
),
);
}),
),
),
I am damn sure its because futurebuilder keeps calling function which is returning data but because of keeps calling functions my Futurebuilder keeps showing loading.
You should not call setState inside the future that you are giving to the FutureBuilder.
The state actualization will cause the FutureBuilder to re-build. Meaning triggering the future again, and ... infinite loop !