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,
),
),
],
),
),
],
)
],
);
},
);
Related
Currently, I am working on a Flutter project which is a tricycle booking system. I am developing two mobile apps in flutter, one for the passenger, and another for the driver. The functionality that I'm having a problem is that a passenger should ask or request a driver for his/her booking. On the driver's side, the driver will be able to see the list of active passengers (these are those who requested a ride). All these rides are stored in a list called pList. When a modal popup displays all the items (passengers that request a ride) in the pList, and then the driver chose one, the passenger data that is being fetched is only the passenger who FIRST requested a ride or the first item being listed in the list, and not the one who the driver has chosen. Do you have any idea why and how will I fix this problem?
What I want to happen is when the driver clicked on passenger C, passenger C data will be fetched and not passenger A (first to request). Any help will be much appreciated.
Here is my code:
readUserInformation(BuildContext context) async
{
Object? empty = "";
var passengerListKeys = Provider.of<AppInfo>(context, listen: false).activePassengerList;
for(String eachPassengerKey in passengerListKeys)
{
FirebaseDatabase.instance.ref()
.child("All Ride Requests")
.child(eachPassengerKey)
.once()
.then((snapData)
{
if(snapData.snapshot.value != null)
{
var passengerRequestInfo = snapData.snapshot.value;
if (passengerRequestInfo.toString() == empty.toString())
{
print("Same lang");
return null;
}
else
{
empty = passengerRequestInfo;
setState(() {
pList.add(passengerRequestInfo);
});
print("pList: " + pList.toString());
}
double originLat = double.parse((snapData.snapshot.value! as Map)["origin"]["latitude"]);
double originLng = double.parse((snapData.snapshot.value! as Map)["origin"]["longitude"]);
String originAddress = (snapData.snapshot.value! as Map)["originAddress"];
double destinationLat = double.parse((snapData.snapshot.value! as Map)["destination"]["latitude"]);
double destinationLng = double.parse((snapData.snapshot.value! as Map)["destination"]["longitude"]);
String destinationAddress = (snapData.snapshot.value! as Map)["destinationAddress"];
String userName = (snapData.snapshot.value! as Map)["username"];
String userId = (snapData.snapshot.value! as Map)["id"];
// String userPhone = (snapData.snapshot.value! as Map)["phone"];
String? rideRequestId = snapData.snapshot.key;
UserRideRequestInformation userRideRequestDetails = UserRideRequestInformation();
userRideRequestDetails.originLatLng = LatLng(originLat, originLng);
userRideRequestDetails.originAddress = originAddress;
userRideRequestDetails.destinationLatLng = LatLng(destinationLat, destinationLng);
userRideRequestDetails.destinationAddress = destinationAddress;
userRideRequestDetails.userName = userName;
userRideRequestDetails.userId = userId;
// userRideRequestDetails.userPhone = userPhone;
userRideRequestDetails.rideRequestId = rideRequestId;
showDialog(
context: context,
builder: (BuildContext context) => ConfirmDialogBox(
userRideRequestDetails: userRideRequestDetails,
),
);
}
else
{
Fluttertoast.showToast(msg: "This Ride Request Id do not exist.");
}
});
}
}
This is the UI for the modal popup:
import 'package:ehatid_driver_app/new_trip_screen.dart';
import 'package:ehatid_driver_app/user_ride_request_information.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:responsive_sizer/responsive_sizer.dart';
import 'global.dart';
class ConfirmDialogBox extends StatefulWidget
{
UserRideRequestInformation? userRideRequestDetails;
ConfirmDialogBox({this.userRideRequestDetails});
#override
State<ConfirmDialogBox> createState() => _ConfirmDialogBoxState();
}
class _ConfirmDialogBoxState extends State<ConfirmDialogBox>
{
final currentFirebaseUser = FirebaseAuth.instance.currentUser!;
#override
Widget build(BuildContext context)
{
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
backgroundColor: Colors.transparent,
elevation: 2,
child: Container(
margin: const EdgeInsets.all(8),
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.white,
),
child: ListView.builder(
itemCount: pList.length,
itemBuilder: (BuildContext context, int index)
{
return GestureDetector(
onTap: ()
{
setState(() {
chosenPassengerId = pList[index]["id"].toString();
print("Passenger Id: " + chosenPassengerId.toString());
FirebaseDatabase.instance.ref()
.child("passengers")
.child(chosenPassengerId!)
.once()
.then((snap)
{
print("Snap: " + snap.toString());
if(snap.snapshot.value != null)
{
//send notification to that specific driver
// sendNotificationToDriverNow(chosenPassengerId!);
//Display Waiting Response from a Driver UI
// showWaitingResponseFromPassengerUI();
print("Waiting for Response");
//Response from the driver
FirebaseDatabase.instance.ref()
.child("passengers")
.child(chosenPassengerId!)
.child("newRideStatus")
.set("accepted");
FirebaseDatabase.instance.ref()
.child("passengers")
.child(chosenPassengerId!)
.child("newRideStatus")
.onValue.listen((eventSnapshot)
{
//accept the ride request push notification
//(newRideStatus = accepted)
if(eventSnapshot.snapshot.value == "accepted")
{
//design and display ui for displaying driver information
rideRequest(context);
print("accepted");
}
});
}
else
{
Fluttertoast.showToast(msg: "This passenger do not exist. Try again.");
}
});
});
// Navigator.pop(context, "passengerChoosed");
},
child: Card(
color: Colors.white54,
elevation: 3,
shadowColor: Colors.green,
margin: EdgeInsets.all(8.0),
child: ListTile(
title: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 6.0),
child: Text(
pList[index]["username"],
style: const TextStyle(
fontFamily: 'Montserrat',
fontSize: 16,
color: Color(0xFF272727),
fontWeight: FontWeight.bold,
),
),
),
Icon(
Icons.verified_rounded,
color: Color(0xFF0CBC8B),
),
],
),
SizedBox(height: 1.h,),
//icon + pickup
Row(
children: [
Image.asset(
"assets/images/origin.png",
height: 26,
width: 26,
),
const SizedBox(width: 12,),
Expanded(
child: Container(
child: Text(
pList[index]["originAddress"],
style: const TextStyle(
fontFamily: 'Montserrat',
fontSize: 14,
color: Color(0xFF272727),
),
),
),
),
],
),
SizedBox(height: 1.h,),
Row(
children: [
Image.asset(
"assets/images/destination.png",
height: 26,
width: 26,
),
const SizedBox(width: 12,),
Expanded(
child: Container(
child: Text(
pList[index]["destinationAddress"],
style: const TextStyle(
fontFamily: 'Montserrat',
fontSize: 14,
color: Color(0xFF272727),
),
),
),
),
],
),
],
),
),
),
);
},
),
),
);
}
rideRequest(BuildContext context)
{
String getRideRequestId="";
FirebaseDatabase.instance.ref()
.child("drivers")
.child(currentFirebaseUser.uid)
.child("newRideStatus")
.set(widget.userRideRequestDetails!.rideRequestId);
FirebaseDatabase.instance.ref()
.child("drivers")
.child(currentFirebaseUser.uid)
.child("newRideStatus")
.once()
.then((snap)
{
if(snap.snapshot.value != null)
{
getRideRequestId = snap.snapshot.value.toString();
}
else
{
Fluttertoast.showToast(msg: "This ride request do not exists.");
}
if(getRideRequestId == widget.userRideRequestDetails!.rideRequestId)
{
FirebaseDatabase.instance.ref()
.child("drivers")
.child(currentFirebaseUser.uid)
.child("newRideStatus")
.set("accepted");
Fluttertoast.showToast(msg: "Accepted Successfully.");
//trip started now - send driver to new tripScreen
Navigator.push(context, MaterialPageRoute(builder: (c)=> NewTripScreen(
userRideRequestDetails: widget.userRideRequestDetails,
)));
}
else
{
Fluttertoast.showToast(msg: "This Ride Request do not exists.");
}
});
}
}
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 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 !
I am showing list-builder i need to show just a static data right now I am just check itemCount right now later'll show data but it's showing error .
Here is my code
class _OrderPageState extends State<OrderPage> {
bool showCards = false;
var data;
#override
void initState() {
this.getOrders();
}
getOrders() async{
final storage = new FlutterSecureStorage();
String userId = await storage.read(key: "_userID");
String url =
'http://retailapi.airtechsolutions.pk/api/orders/customer/${userId}/0';
print(url);
http.Response res = await http.get(
url,
);
var data = json.decode(res.body.toString());
print(data);
if(data['description'].toString() == "Success"){
print(data['Orders']);
print(data['Orders'].length); //its printing 6 here
setState(() {
showCards = true;
});}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Order', style: Theme.of(context).textTheme.headline4),
),
body: showCards ? Container(
child: ListView.builder(
itemCount: data['Orders'].length,
shrinkWrap: true,
padding: EdgeInsets.symmetric(horizontal: 18.0, vertical: 20.0),
itemBuilder: (context, index) {
var order = orderList[index];
return SideInAnimation(index, child:GestureDetector(
onTap: () {
// Get.to(OrderDetailPage(order: order));
},
child: Container(
width: double.infinity,
padding: EdgeInsets.all(12.0),
margin: EdgeInsets.only(bottom: 15.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
border: Border.all(color: Theme.of(context).accentColor),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(order.id,
style: Theme.of(context)
.textTheme
.headline3
.copyWith(color: Theme.of(context).primaryColor)),
SizedBox(height: 12.0),
Text(order.dateOrder, style: Theme.of(context).textTheme.subtitle2),
Divider(),
orderCardItem(context,
title: "order.orderstatus", data: order.orderStatus),
SizedBox(height: 12.0),
orderCardItem(context,
title: "order.items",
data: "${order.totalItem} " + tr("order.itemspurchased")),
SizedBox(height: 12.0),
priceItem(context,
title: "order.price", data: "\$ ${order.totalPrice}"),
],
),
),
));
},
),
) : Container(),
);
}
}
In my function its printing the length by in List builder its showing an error that Tried calling: ` But on the print where API load it's showing the length 6.
First you need to initalize a list or array then simply add your data into that variable and then call this variable to your listview builder
var ordersData = [];
then your getData() method should be like this
getOrders() async {
...
if (data['description'].toString() == "Success") {
ordersData.add(data['Orders']); // Add your data to array or list
print(ordersData.length); //its printing 6 here
}
...
}
Here your Listview like this
ListView.builder(
itemCount: ordersData.length, // Here you need to pass this lenght
...
)
I have page Navigate to second page with variable (dID) with await to return same value if it has been changed ,at the second page if i did't do anything the value must return without any changes ,if i changed slider the value of (dID) must be increase by (1) ,but when i Navigate.pop the return value is same without increasing.
New update : After many test i did the problem is in the second page ,when i change the slider value i call a function to get the new value (newSavedDayId) ,and it is get it correctly but just inside the function ,after the slider change and get the new value ,it is returned to null :
newSavedDayId = Instance of 'Future<dynamic>'
second page which return value :
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import '../classes/viewdigree.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Days extends StatefulWidget {
#override
_DaysState createState() => _DaysState();
}
TextEditingController insertedDegree = TextEditingController();
class _DaysState extends State<Days> {
#override
Widget build(BuildContext context) {
List digrees = [];
var widthView = MediaQuery.of(context).size.width;
Map rdata = ModalRoute.of(context).settings.arguments;
var did = int.parse(rdata['dayId'].toString());
var u_id = rdata['userID'];
var m_id = rdata['courseId'];
var lang = rdata['lang'];
int w_id;
var newSavedDayId = rdata['savedDayID']; ----// received value
var username;
if (did <= 6) {
w_id = 1;
} else if (did <= 12) {
w_id = 2;
} else if (did <= 18) {
w_id = 3;
} else {
w_id = 4;
}
Future<List> fetchDigrees() async {
var url =
'https://srdtraining.com/api/controller/activities/activiy_list.php?d_id=$did&m_id=$m_id&u_id=$u_id';
var response = await http.get(url);
var data = jsonDecode(response.body);
print(data);
for (var x in data) {
Digree newdigree = Digree(
x['index'],
x['title_k'],
x['title_a'],
x['aya'],
x['link'],
x['activity_k'],
x['activity_a'],
x['act_id'],
x['mydigree']);
digrees.add(newdigree);
}
return digrees;
}
// Insert Func
send_degree(uId, actId, degree, w_id, did, m_id) async {
var sendData = {
'u_id': uId.toString(),
'act_id': actId.toString(),
'digree': degree.toString(),
'm_id': m_id.toString(),
'd_id': did.toString(),
'w_id': w_id.toString()
};
var url = 'https://srdtraining.com/api/controller/data/changedata.php';
var response = await http.post(url, body: sendData);
}
// End of Insert Func
//get user status .................. // this is the function to get new value
void getUserStatus() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
setState(() {
username = preferences.getString('username');
});
var url =
"http://srdtraining.com/api/controller/users/status_user.php?username=$username";
var response = await http.get(url);
var data = jsonDecode(response.body);
setState(() {
newSavedDayId = int.parse(data['d_id']); ----// Set New value by getting it from API after increasing by server.
});
print('newSavedDayId = $newSavedDayId');----// here it is print new value with increasing correctly
}
// End get user
return FutureBuilder(
future: fetchDigrees(),
builder: (context, snapshot) {
if (snapshot.data == null) {
return Scaffold(
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('./assets/images/background.png'),
fit: BoxFit.cover)),
child: Center(
child: Text("Loading"),
),
),
);
} else {
YoutubePlayerController _controller = YoutubePlayerController(
initialVideoId: snapshot.data[0].link,
flags: YoutubePlayerFlags(
autoPlay: false,
mute: false,
));
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context, newSavedDayId);
}),
backgroundColor: Colors.pink[900],
title: Text(
'ژیان و قورئان',
style: TextStyle(fontSize: 32),
),
centerTitle: true,
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('./assets/images/background.png'),
fit: BoxFit.cover)),
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: ListView(
padding: EdgeInsets.fromLTRB(25, 20, 25, 20),
shrinkWrap: true,
children: <Widget>[
Text(
lang == 'k'
? snapshot.data[0].title_k
: snapshot.data[0].title_a,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 32, color: Colors.white)),
//for top margin
SizedBox(height: 20.0),
// dexription
Container(
padding: const EdgeInsets.all(15),
width: widthView,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
color: const Color.fromRGBO(180, 80, 80, 0.3)),
child: Text(snapshot.data[0].aya,
textAlign: TextAlign.justify,
textDirection: TextDirection.rtl,
style: TextStyle(
fontFamily: 'Hafs',
fontSize: 26,
color: Colors.greenAccent[100])),
),
// now populating your ListView for `Directionality`
Column(
children: <Widget>[
// Start activities
Column(
children: snapshot.data.map<Widget>((item) {
double _value =
double.parse(item.mydigree.toString());
return Directionality(
textDirection: TextDirection.rtl,
child: Column(
children: <Widget>[
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
border: Border.all(
width: 2, color: Colors.white),
color:
Color.fromRGBO(230, 200, 200, 0.2)),
width: widthView,
padding: EdgeInsets.all(25),
margin: EdgeInsets.fromLTRB(0, 25, 0, 25),
child: Column(
children: <Widget>[
Text(
lang == 'k'
? item.activity_k
: item.activity_a,
textAlign: TextAlign.justify,
style: TextStyle(
fontSize: 28, color: Colors.white),
),
SizedBox(
height: 15,
),
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.yellow[200]
.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 20,
)
],
borderRadius:
BorderRadius.circular(15),
color:
Color.fromRGBO(0, 0, 0, 0.4)),
width: widthView,
padding: EdgeInsets.all(10),
child: Slider(
max: 100,
min: 0,
divisions: 100,
value: _value,
label: _value.round().toString(),
onChanged: (val) {
send_degree(u_id, item.act_id,
val, w_id, did, m_id);
},
onChangeEnd: (val) {
setState(() {
_value = val;
});
getUserStatus(); /// when i print the value here it is give me null
}),
),
SizedBox(
height: 10,
),
Text('$_value',
style: TextStyle(
fontSize: 26,
color: Colors.white))
],
),
)
],
),
);
}).toList()),
// End activities
SizedBox(
height: 20,
),
Text('خەلەکا ئەڤرو',
textAlign: TextAlign.right,
style:
TextStyle(fontSize: 26, color: Colors.yellow)),
SizedBox(
height: 20,
),
YoutubePlayer(
controller: _controller,
showVideoProgressIndicator: true,
progressIndicatorColor: Colors.blueAccent,
),
],
),
],
),
),
);
}
});
}
}
you can usef ValueChanged onChanged and do a callback to the page you want to update ,
you can passe the onChanged funtion on the parametre ,
when you change your value use : onChanged()
than in the page you want to see the update on call your function with set state ,
I solved it by merging two function in one :
Future<List> fetchDigrees() async {
var url =
'https://srdtraining.com/api/controller/activities/activiy_list.php?d_id=$did&m_id=$m_id&u_id=$u_id';
var response = await http.get(url);
var data = jsonDecode(response.body);
print(data);
for (var x in data) {
Digree newdigree = Digree(
x['index'],
x['title_k'],
x['title_a'],
x['aya'],
x['link'],
x['activity_k'],
x['activity_a'],
x['act_id'],
x['mydigree']);
digrees.add(newdigree);
}
return digrees;
}
void getUserStatus() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
setState(() {
username = preferences.getString('username');
});
var url =
"http://srdtraining.com/api/controller/users/status_user.php?username=$username";
var response = await http.get(url);
var data = jsonDecode(response.body);
setState(() {
newSavedDayId = int.parse(data['d_id']); ----// Set New value by getting it from API after increasing by server.
});
and they now like this and worked correctly :
Future<List> fetchDigrees() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
username = preferences.getString('username');
var url1 =
"http://srdtraining.com/api/controller/users/status_user.php?username=$username";
var response1 = await http.get(url1);
var data1 = jsonDecode(response1.body);
newSavedDayId = int.parse(data1['d_id']);
print('newSavedDayId before retrun = $newSavedDayId');
var url =
'https://srdtraining.com/api/controller/activities/activiy_list.php?d_id=$did&m_id=$m_id&u_id=$u_id';
var response = await http.get(url);
var data = jsonDecode(response.body);
print(data);
for (var x in data) {
Digree newdigree = Digree(
x['index'],
x['title_k'],
x['title_a'],
x['aya'],
x['link'],
x['activity_k'],
x['activity_a'],
x['act_id'],
x['mydigree']);
digrees.add(newdigree);
}
return digrees;
}