FutureBuilder not triggered after Navigator.pop - flutter

In my app, the FutureBuilder works fine when I use BottomNavigationBarItem (cf Home widget).
However, when I user Navigator.push and Navigator.pop, the FutureBuilder is not triggered.
I can't understand why, any help would be highly appreciated.
Bellow my code.
Home widget
import 'package:com.pro.cocotal.online/models/product.dart';
import 'package:com.pro.cocotal.online/models/user.dart';
import 'package:com.pro.cocotal.online/screens/home/products/productListScreen.dart';
import 'package:com.pro.cocotal.online/screens/home/shopSettings/shopSettings.dart';
import 'package:flutter/material.dart';
class Home extends StatefulWidget {
final User user;
final List<Product> products;
Home(this.user, this.products);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
int _selectedIndex = 0;
List<Widget> _widgetOptions;
#override
void initState(){
_widgetOptions = <Widget>[
ProductListScreen(widget.user, widget.products),
ShopSettings(widget.user),
];
}
//navigue dans les menus
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body:Center(
child: Scaffold(
body:_widgetOptions.elementAt(_selectedIndex),
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(
title: Text(''),
icon: Icon(Icons.home, color: Colors.blueAccent, size: 35),
),
BottomNavigationBarItem(
title: Text(''),
icon: Icon(Icons.settings, color: Colors.blueAccent, size: 35)
)
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
),
)
);
}
}
ProductListScreen class
import 'package:com.pro.cocotal.online/models/product.dart';
import 'package:com.pro.cocotal.online/models/user.dart';
import 'package:com.pro.cocotal.online/screens/home/products/addProductScreen.dart';
import 'package:com.pro.cocotal.online/screens/home/products/productScreen.dart';
import 'package:com.pro.cocotal.online/services/productService.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
class ProductListScreen extends StatefulWidget {
final List<Product> products;
final User user;
ProductListScreen(this.user, this.products);
#override
_ProductsState createState() => _ProductsState();
}
class _ProductsState extends State<ProductListScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Tienda " + widget.user.storeName),
elevation: 0,
),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Expanded(
child: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
backgroundColor: Colors.blue,
expandedHeight: 130,
flexibleSpace: FlexibleSpaceBar(
background: Image.network(
"https://cocotal.online/wp-content/uploads/revslider/cropped-slider-41.jpg",
fit: BoxFit.cover,
),
),
),
FutureBuilder(
future: ProductService().getProducts(widget.user),
builder: (context, productSnaps){
List<Product> products = productSnaps.data;
if (productSnaps.connectionState != ConnectionState.done) {
return SliverFixedExtentList(
itemExtent: 1,
delegate: SliverChildBuilderDelegate(
(context, i) {
return SpinKitRotatingCircle(
color: Colors.white,
size: 50.0,
);
},
childCount: 1,
),
);
}
if (productSnaps.hasData == null) {
return SliverFixedExtentList(
itemExtent: 0,
delegate: SliverChildBuilderDelegate(
(context, i) {
return ListTile(
title: Text("null"),
trailing: Icon(Icons.delete),
onTap: () {
},
);
},
childCount: 1,
),
);
}
return SliverFixedExtentList(
itemExtent: 50,
delegate: SliverChildBuilderDelegate(
(context, i) {
return ListTile(
title: Text(products[i].name),
trailing: Icon(Icons.delete),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => ProductScreen(products[i])));
},
);
},
childCount: products.length,
),
);
},
),
],
),
),
RaisedButton.icon(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => AddProduct()));
},
icon: Icon(Icons.add_circle),
label: Text('Add a product')
),
],
)
);
}
}
ProductScreen class
import 'package:com.pro.cocotal.online/models/product.dart';
import 'package:flutter/material.dart';
class ProductScreen extends StatefulWidget {
final Product product;
const ProductScreen(this.product);
#override
_ProductScreenState createState() => _ProductScreenState();
}
class _ProductScreenState extends State<ProductScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.product.name),
leading: IconButton(icon: Icon(Icons.arrow_back), onPressed: ()async{
Navigator.pop(context);
}),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Row(
children: <Widget>[
Text("Nom : " + widget.product.name),
],
),
Row(
children: <Widget>[
Text("Description : " + widget.product.description),
],
),
Row(
children: <Widget>[
Text("Prix : " + widget.product.price),
],
),
],
),
);
}
}

Related

In Flutter CupertinoTabBar + StreamBuilder code is running but widgets are not rebuilt

I have a 2 tab screen where I want to dynamically rebuild the content depending on user's interactions. On the first tab there are multiple states which I try to handle by setting a current step name using model and provider. For the second screen after pressing a button I get the print message in a console but the content of CupertinoTabView remains unchanged.
Minimum runnable code snippet:
main.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:my_app/screens/login.dart';
import 'package:my_app/screens/tab_bar.dart';
import 'package:my_app/models/model.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
return runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => Model(),
),
],
child: CupertinoApp(
theme: const CupertinoThemeData(
brightness: Brightness.light,
scaffoldBackgroundColor: CupertinoColors.white,
),
initialRoute: '/',
routes: {
'/': (context) => LoginScreen(),
'/tab_bar': (context) => TabBarScreen(),
//'/add_item': (context) => AddItemScreen(),
},
),
);
}
}
login.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:my_app/models/model.dart';
class LoginScreen extends StatelessWidget {
final model = Model();
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('app',),
),
child: Container(
alignment: FractionalOffset.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
child: Text('next'),
onPressed: (){
model.setStep('step1');
Navigator.pushNamed(context, '/tab_bar');
},
style: ElevatedButton.styleFrom(
primary: CupertinoColors.white,
side: BorderSide(color: Colors.blue, width: 2.0)
),
),
]
),
),
);
}
}
tab_bar.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:my_app/models/model.dart';
class TabBarScreen extends StatefulWidget {
#override
State createState() => TabBarScreenState();
}
class TabBarScreenState extends State<TabBarScreen> {
final model = Model();
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
print(model.getStep);
return Consumer<Model>(
builder: (context, model, _) => CupertinoTabScaffold(
tabBar: CupertinoTabBar(
backgroundColor: CupertinoColors.white,
inactiveColor: Colors.blue,
activeColor: Colors.blueAccent,
border: const Border(
top: BorderSide(
color: CupertinoColors.activeBlue,
width: 2.0,
),
),
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.favorite_outline_outlined),
),
BottomNavigationBarItem(
icon: Icon(Icons.more_vert_sharp),
),
],
),
tabBuilder: (context, index) {
late final CupertinoTabView returnValue;
switch (index) {
case 0:
if (model.getStep == 'step1') {
print('step1');
returnValue = CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: SafeArea(
child: GestureDetector(
onTap: (){ },
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
margin: const EdgeInsets.only(bottom: 15.0),
child: FloatingActionButton(
onPressed: () { model.setStep('step2'); setState(() {
}); },
tooltip: 'step2',
child: Icon(Icons.add),
backgroundColor: CupertinoColors.white,
foregroundColor: CupertinoColors.black,
),
),
],
),
],
),
),
),
);
});
}
else if (model.getStep == 'step2') {
print('step2');
returnValue = CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: SafeArea(
child: Column(
children: <Widget> [
Text('step2'),
],
),
),
);
});
}
else {
returnValue = CupertinoTabView(builder: (context) {
return Container();
});
}
break;
case 1:
returnValue = CupertinoTabView(builder: (context) {
return CupertinoPageScaffold(
child: Text("Tab2"),
);
});
break;
}
return returnValue;
},
),
);
}
}
model.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class Model extends ChangeNotifier {
static String currentStep = 'login';
// login
// step1 - step1
// step2 - step2
String get getStep {
return currentStep;
}
void setStep(String step) {
currentStep = step;
notifyListeners();
}
}
I want the tab to rebuild on pressing a button from step1 to show the step2 content. In a console I can see the print of 'step2' when pressing, but the actual tab remains unchanged.
Appreciate your help
Since nobody have answered I figured it out on my own.
The resolution is to use Navigator like this:
onPressed: () {
Navigator.of(context).push(
CupertinoPageRoute<void>(
builder: (BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('Page 2 of tab'),
),
child: Center(
child: CupertinoButton(
child: const Text('Back'),
onPressed: () { Navigator.of(context).pop(); },
),
),
);
},
),
);
},
and therefore you won't need 'else if' conditioning.

Call set state of FirstScreen from SecondScreen in Flutter

I have two screens in flutter named 'FirstScreen' with list of orders and 'SecondScreen' for certain actions.
I would like to call setstate of 'FirstScreen' on 'SecondScreen' pop, so that the 'FirstScreen' will reload list of pending orders
SecondScreen will accept or reject orders and it FirstScreen should reload data from server, which is called by method getOrders() in FirstScreen.
FirstScreen Code
import 'package:flutter/material.dart';
import 'package:nobleappshop/model/jobOrderItem.dart';
import 'package:nobleappshop/screens/SeconScreen.dart';
import 'package:nobleappshop/constants/constants.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class FirstScreen extends StatefulWidget {
#override
FirstScreenState createState() => FirstScreenState();
}
class FirstScreenState extends State<FirstScreen> {
Future<List<JobOrders>> _getPendingOrder() async {
var data = await http.get("$ApiServer/JobOrders/smOrdersPending");
var jsonData = json.decode(data.body);
List<JobOrders> joborderitemlist = [];
for (var i in jsonData) {
JobOrders jobOrders = JobOrders(
Eid: i["Eid"],
Uid: i["Uid"],
Name: i["Name"],
Contact: i["Contact"].toString(),
OrderStat: i["OrderStat"],
);
joborderitemlist.add(jobOrders);
}
return joborderitemlist;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('FirstScreen'),
),
body: FutureBuilder(
future: _getPendingOrder(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data.length <= 0) {
return Container(
child: Center(
child: Text('You have not made any orders yet...'),
),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return OrdersListWidget(
Eid: snapshot.data[index].Eid,
Uid: snapshot.data[index].Uid.toString(),
Name: snapshot.data[index].Name.toString(),
Contact: snapshot.data[index].Contact.toString(),
Status: snapshot.data[index].OrderStat.toString(),
);
},
);
}
} else {
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
}
},
),
);
}
}
class OrdersListWidget extends StatelessWidget {
int Eid;
String Uid;
String Name;
String Contact;
String Status;
OrdersListWidget(
{#required this.Eid,
#required this.Uid,
#required this.Name,
#required this.Contact,
#required this.Status});
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
ListTile(
leading: Text('#$Eid'),
title: Text(Name),
subtitle: Text(Contact),
trailing: Text(Status),
onTap: () {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) => SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: SecondScreen(OrderId: Eid),
),
),
);
},
),
Divider(),
],
);
}
}
SecondScreen Code
import 'package:flutter/material.dart';
import 'package:nobleappshop/model/orderItem.dart';
import 'package:http/http.dart' as http;
import 'package:nobleappshop/widgets/iconTextWidget.dart';
import 'package:nobleappshop/widgets/scOrderItems.dart';
import 'package:nobleappshop/constants/constants.dart';
class SecondScreen extends StatefulWidget {
int OrderId;
SecondScreen({#required this.OrderId});
#override
_SecondScreenState createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> {
Future<http.Response> _updateJobOrder() async {
//Run Update code here
}
double totalAmount = 0;
String token;
List<OrderItem> orderitemlist = [];
Future<List<OrderItem>> _getMyOrders() async {
//Call for orderitemslist
return orderitemlist;
}
#override
void initState() {
super.initState();
_getMyOrders();
}
#override
Widget build(BuildContext context) {
return Container(
color: Color(0xff757575),
child: Container(
padding: EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
IconTextRowWidget(btnIcon: Icons.credit_card,btnText: 'Amount Due',btnSubText: '${totalAmount<10?10:totalAmount} QAR',),
Row(
children: <Widget>[
Expanded(
child: FlatButton(
color: Colors.green,
onPressed: (){
// Here I would like to close my current screen and reload orderslist, so that it will load all other pending joborders
_updateJobOrder();
Navigator.pop(context);
},
child: Text('Approve',style: TextStyle(color: Colors.white),),
),
),
Expanded(
child: FlatButton(
color: Colors.blueGrey,
onPressed: (){
// Here I would like to close my current screen and reload orderslist, so that it will load all other pending joborders
_updateJobOrder();
Navigator.pop(context);
},
child: Text('Reject',style: TextStyle(color: Colors.white),),
),
),
],
),
SizedBox(height: 10,)
// SizedBox(
// height: 30.0,
// ),
],
),
),
);
}
}
When I checked your code I realized that you need to send function to the grandchild of your first widget,
You need to declare a function in your OrdersListWidget because this widget is only way to access the second screen.
class OrdersListWidget extends StatelessWidget {
int Eid;
String Uid;
String Name;
String Contact;
String Status;
final VoidCallback setStateOfFirstScreen;
OrdersListWidget(
{#required this.Eid,
#required this.Uid,
#required this.Name,
#required this.Contact,
#required this.Status,
#required this.setStateOfFirstScreen});
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
ListTile(
leading: Text('#$Eid'),
title: Text(Name),
subtitle: Text(Contact),
trailing: Text(Status),
onTap: () {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) => SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: SecondScreen(OrderId: Eid, setStateOfFirstScreen: setStateOfFirstScreen),
),
),
);
},
),
Divider(),
],
);
}
}
And send setState to the OrdersListWidget as a parameter in your first page;
ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return OrdersListWidget(
Eid: snapshot.data[index].Eid,
Uid: snapshot.data[index].Uid.toString(),
Name: snapshot.data[index].Name.toString(),
Contact: snapshot.data[index].Contact.toString(),
Status: snapshot.data[index].OrderStat.toString(),
setStateOfFirstScreen: () => setState(() {}),
);
},
);
Send the setStateOfFirstScreen to the SecondScreen and use it there to setState of the first screen;
class SecondScreen extends StatefulWidget {
final int OrderId;
final VoidCallback setStateOfFirstScreen;
SecondScreen({#required this.OrderId, #required this.setStateOfFirstScreen});
#override
_SecondScreenState createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> {
Future<http.Response> _updateJobOrder() async {
//Run Update code here
}
double totalAmount = 0;
String token;
List<OrderItem> orderitemlist = [];
Future<List<OrderItem>> _getMyOrders() async {
//Call for orderitemslist
return orderitemlist;
}
#override
void initState() {
super.initState();
_getMyOrders();
}
#override
Widget build(BuildContext context) {
return Container(
color: Color(0xff757575),
child: Container(
padding: EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
IconTextRowWidget(
btnIcon: Icons.credit_card,
btnText: 'Amount Due',
btnSubText: '${totalAmount < 10 ? 10 : totalAmount} QAR',
),
Row(
children: <Widget>[
Expanded(
child: FlatButton(
color: Colors.green,
onPressed: () {
// Here I would like to close my current screen and reload orderslist, so that it will load all other pending joborders
_updateJobOrder();
Navigator.pop(context);
widget.setStateOfFirstScreen();
},
child: Text(
'Approve',
style: TextStyle(color: Colors.white),
),
),
),
Expanded(
child: FlatButton(
color: Colors.blueGrey,
onPressed: () {
// Here I would like to close my current screen and reload orderslist, so that it will load all other pending joborders
_updateJobOrder();
Navigator.pop(context);
widget.setStateOfFirstScreen();
},
child: Text(
'Reject',
style: TextStyle(color: Colors.white),
),
),
),
],
),
SizedBox(
height: 10,
)
// SizedBox(
// height: 30.0,
// ),
],
),
),
);
}
}
You can declare a void call back or a function as a property of second screen and send it from first screen; here is an example;
class SecondScreen extends StatelessWidget {
final VoidCallback setStateOfFirstScreen;
const SecondScreen({Key key, this.setStateOfFirstScreen}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(icon: Icon(Icons.refresh), onPressed: setStateOfFirstScreen),
],
),
body: Center(),
);
}
}
class FistScreen extends StatefulWidget {
#override
_FistScreenState createState() => _FistScreenState();
}
class _FistScreenState extends State<FistScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: FlatButton(
child: Text("Go to the second screen"),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (c) => SecondScreen(
setStateOfFirstScreen: () => setState(() {}),
),
),
);
},
),
),
);
}
}

Am Trying To calculate total price of a List of items

am making a shopping cart app where I want to calculate the total price of the products present in the cart I made a function for it and tried executing in init state but it's not working
import 'package:flutter/material.dart';
import 'package:shop/Models/Database.dart';
class Cart extends StatefulWidget {
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
int sum = 0;
total() {
studlist.forEach((element) {
sum = sum + element.price;
});
}
#override
void initState() {
total();
super.initState();
}
final DbStudentManager dbmanager = new DbStudentManager();
Student cart;
List<Cart> cartList;
int updateIndex;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'Cart',
style: TextStyle(color: Colors.black),
),
),
body: FutureBuilder(
future: dbmanager.getStudentList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
studlist = snapshot.data;
}
return ListView.builder(
itemCount: studlist == null ? 0 : studlist.length,
itemBuilder: (BuildContext context, int index) {
Student ct = studlist[index];
return Card(
child: ListTile(
title: Text(ct.name),
subtitle: Text('${ct.price}'),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
dbmanager.deleteStudent(ct.id);
setState(() {
studlist.remove(index);
});
}),
),
);
});
}),
bottomNavigationBar: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Text('$sum'),
SizedBox(
width: 10,
),
Text('Check Out'),
],
),
),
],
),
);
}
}
the error I get:
The method 'forEach' was called on null.
Receiver: null
Tried calling: forEach(Closure: (Student) => Null)
Try this:
import 'package:flutter/material.dart';
import 'package:shop/Models/Database.dart';
class Cart extends StatefulWidget {
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
int sum = 0;
#override
void initState() {
super.initState();
}
final DbStudentManager dbmanager = new DbStudentManager();
Student cart;
List<Cart> studList=[];
int updateIndex;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'Cart',
style: TextStyle(color: Colors.black),
),
),
body: FutureBuilder(
future: dbmanager.getStudentList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
studlist = snapshot.data;
studlist.forEach((element) {
setState((){
sum = sum + element.price;
});
});
}
return ListView.builder(
itemCount: studlist == null ? 0 : studlist.length,
itemBuilder: (BuildContext context, int index) {
Student ct = studlist[index];
return Card(
child: ListTile(
title: Text(ct.name),
subtitle: Text('${ct.price}'),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
dbmanager.deleteStudent(ct.id);
setState(() {
studlist.remove(index);
});
}),
),
);
});
}),
bottomNavigationBar: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Text('$sum'),
SizedBox(
width: 10,
),
Text('Check Out'),
],
),
),
],
),
);
}
}
Try running total() function if the data when the data is loaded, not in init. As data is initially empty, running it inside init will cause this error.
if (snapshot.hasData) {
studlist = snapshot.data;
total();
}
Full Code:
import 'package:flutter/material.dart';
import 'package:shop/Models/Database.dart';
class Cart extends StatefulWidget {
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
int sum = 0;
total() {
studlist.forEach((element) {
sum = sum + element.price;
});
}
final DbStudentManager dbmanager = new DbStudentManager();
Student cart;
List<Cart> cartList;
int updateIndex;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
'Cart',
style: TextStyle(color: Colors.black),
),
),
body: FutureBuilder(
future: dbmanager.getStudentList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
studlist = snapshot.data;
total(); //Run the total() function here
}
return ListView.builder(
itemCount: studlist == null ? 0 : studlist.length,
itemBuilder: (BuildContext context, int index) {
Student ct = studlist[index];
return Card(
child: ListTile(
title: Text(ct.name),
subtitle: Text('${ct.price}'),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
dbmanager.deleteStudent(ct.id);
setState(() {
studlist.remove(index);
});
}),
),
);
});
}),
bottomNavigationBar: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(10),
child: Row(
children: <Widget>[
Text('$sum'),
SizedBox(
width: 10,
),
Text('Check Out'),
],
),
),
],
),
);
}
}
try this
If I added Quantity increased totalQty but I have one issue if I removing Item in list
did not decrease. sorry my english not good
`total() {
studlist.forEach((element) {
if(element.qty!=null){
totalQty=totalQty+element.qty;
print(totalQty);
}
});
}
`

Flutter: Card() / Firebase - (Beginner problem)

I am new in Flutter. I have a problem with a small project. I collect data from a Firebase DB and adding it into a listTile. I am trying to add 2 static ListTile but they are added to the homescreen for every loop. I can't get a out of the loop - Any one there are willing to help.
The "Datablade" and "Vejledning" listtile are added for every loop
'''
import 'package:flutter/material.dart';
import 'package:flutter_app/services/auth.dart';
import 'package:flutter_app/services/database.dart';
import 'package:provider/provider.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
//import 'package:flutter_app/screens/home/brew_list.dart';
import 'package:flutter_app/models/brew.dart';
class Home extends StatelessWidget {
final AuthService _auth = AuthService();
#override
Widget build(BuildContext context) {
return StreamProvider<List<Brew>>.value(
value: DatabaseService().filer,
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text('Arbejdsmiljø'),
backgroundColor: Colors.orange[400],
elevation: 0.0,
actions: <Widget>[
FlatButton.icon(
icon: Icon(Icons.person),
label: Text('Log ud'),
onPressed: () async {
await _auth.signOut();
},
),
],
),
body:
ListPage(),
),
);
//ListPage(),
}
}
class ListPage extends StatefulWidget {
#override
_ListPageState createState() => _ListPageState();
}
class _ListPageState extends State<ListPage> {
Future _data;
Future getPosts() async{
var firestore = Firestore.instance;
QuerySnapshot qn = await firestore.collection('filer').getDocuments();
return qn.documents;
}
navigateToDetail(DocumentSnapshot post) {
Navigator.push(context, MaterialPageRoute(builder: (context) => DetailPage(post: post,)));
}
void initState() {
super.initState();
_data = getPosts();
}
#override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder(
future: _data,
builder: (_, snapshot){
if(snapshot.connectionState == ConnectionState.waiting){
return Center(
child: Text('Loading'),
);
} else {
return ListView.builder(
//return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (_, index){
return Card(
child: Column(
children: <Widget> [
ListTile(
leading: Icon(Icons.star, color: Colors.orange, size: 26.0),
onTap: () => navigateToDetail(snapshot.data[index]),
title: Text('Datablade'),
trailing: Icon(Icons.keyboard_arrow_right),
),
Divider(color: Colors.orange,indent: 16.0),
ListTile(
title: new Center(child: new Text("Vejledninger",
style: new TextStyle(
color: Colors.orange[400],
fontWeight: FontWeight.w500, fontSize: 25.0),)),
),
ListTile(
onTap: () => navigateToDetail(snapshot.data[index]),
title: Text(snapshot.data[index].data["name"]),
leading: CircleAvatar(
backgroundColor: Colors.orange[400],
foregroundColor: Colors.white,
child: Text(snapshot.data[index].data["name"][0])
)
)
],
),
);
//return ListTile(
//title: Text(snapshot.data[index].data["name"]),
//onTap: () => navigateToDetail(snapshot.data[index]),
//);
});
}
}),
);
}
}
class DetailPage extends StatefulWidget {
final DocumentSnapshot post;
DetailPage ({this.post});
#override
_DetailPageState createState() => _DetailPageState();
}
class _DetailPageState extends State<DetailPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.post.data["name"]),
),
body: Container(
child: Card(
child: ListTile(
title: Text(widget.post.data["name"]),
subtitle: Text(widget.post.data['beskrivelse']),
),
),
),
);
}
}
'''

Can someone check my Dart code and tell me where I'm making mistake in returning data from my screen as a ListView

I am stuck here for the past 20 days in returning data in my app from the other screen. I'm new to programming and need help. I've been searching through all the internet to find an answer related to my query but nothing is helping though. I ask my fellow SO guys to please help.
You can look at the entire code which I've made open here.
My code:
class SecondPage extends StatefulWidget {
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(30),
child: Stack(
alignment: Alignment.bottomRight,
children: <Widget>[
FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.blue,
),
onPressed: () async {
final newList = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FavoriteList(),
),
);
setState(() {
return ListView.builder(
itemCount: newList.length,
itemBuilder: (context, index){
return Container(
child: Text('item: $newList'),
);
},
);
});
},
)
],
),
);
}
}
The screen where Navigator.pop() is used:
final Set saved = Set();
class FavoriteList extends StatefulWidget {
#override
_FavoriteListState createState() => _FavoriteListState();
}
class _FavoriteListState extends State<FavoriteList> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add to Favorites!'),
centerTitle: true,
backgroundColor: Colors.red),
body: SafeArea(
child: ListView.builder(
itemCount: 53,
itemBuilder: (context, index) {
return CheckboxListTile(
activeColor: Colors.red,
checkColor: Colors.white,
value: saved.contains(index),
onChanged: (val) {
setState(() {
// isChecked = val; // changed
// if(val == true){ // changed
// __saved.add(context); // changed
// } else{ // changed
// __saved.remove(context); // changed
// } // changed
if (val == true) {
saved.add(index);
} else {
saved.remove(index);
}
});
},
title: Row(
children: <Widget>[
Image.asset('lib/images/${images[index]}'),
SizedBox(
width: 10,
),
Text(nameOfSite[index]),
],
),
);
},
),
),
floatingActionButton: FloatingActionButton(
foregroundColor: Colors.red,
child: Icon(Icons.check),
onPressed: () {
Navigator.pop<Set>(context, saved);
},
),
);
}
}
Here is the SecondPage and FavoriteList that I made
import 'package:flutter/material.dart';
import 'package:aioapp2/lists.dart';
Set<int> favorites = {};
class SecondPage extends StatefulWidget {
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
#override
Widget build(BuildContext context) {
return Stack(
fit: StackFit.expand,
children: <Widget>[
_getFavoriteList(),
Align(
alignment: Alignment.bottomRight,
child: Padding(
padding: const EdgeInsets.all(20.0),
child: FloatingActionButton(
child: Icon(
Icons.edit,
color: Colors.blue,
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => EditFavorites(),
),
).then((updatedFavorites) {
if (updatedFavorites != null)
setState(() {
favorites = updatedFavorites;
});
});
},
),
),
)
],
);
}
Widget _getFavoriteList() {
if (favorites?.isNotEmpty == true)
return _FavoriteList();
else
return _EmptyFavoriteList();
}
}
class _EmptyFavoriteList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Flexible(
child: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Add Your Favorite Sites Here!❤',
style: TextStyle(color: Colors.white),
),
Icon(
Icons.favorite,
size: 150,
color: Colors.blue[100],
),
],
),
),
),
),
],
);
}
}
class _FavoriteList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: favorites.length,
itemBuilder: (context, index) {
return ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage('lib/images/${images[index]}'),
),
title: Text(nameOfSite[favorites.elementAt(index)]),
);
},
);
}
}
//Its FavoriteList Page. I changed the name
class EditFavorites extends StatefulWidget {
#override
_EditFavoritesState createState() => _EditFavoritesState();
}
class _EditFavoritesState extends State<EditFavorites> {
final _editableFavorites = <int>{};
#override
void initState() {
_editableFavorites.addAll(favorites);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add to Favorites!'),
centerTitle: true,
backgroundColor: Colors.red,
actions: <Widget>[
IconButton(
icon: Icon(Icons.done),
onPressed: () {
Navigator.pop<Set>(context, _editableFavorites);
},
)
],
),
//backgroundColor: Colors.indigo,
body: SafeArea(
child: ListView.builder(
itemCount: nameOfSite.length,
itemBuilder: (context, index) {
return ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage('lib/images/${images[index]}'),
),
title: Text(nameOfSite[index]),
trailing: IconButton(
icon: _editableFavorites.contains(index)
? Icon(
Icons.favorite,
color: Colors.red,
)
: Icon(
Icons.favorite_border,
color: Colors.grey,
),
onPressed: () {
setState(() {
if (_editableFavorites.contains(index))
_editableFavorites.remove(index);
else
_editableFavorites.add(index);
});
},
),
);
},
),
),
);
}
}
Just replace secondtab.dart with this code.
You can copy paste run full code below
You have to move out return ListView to the same layer with FloatingActionButton
working demo
full code
import 'package:flutter/material.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 Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SecondPage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
class SecondPage extends StatefulWidget {
#override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
Set newList = {};
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(30),
child: Stack(
alignment: Alignment.bottomRight,
children: <Widget>[
ListView.builder(
itemCount: newList.length,
itemBuilder: (context, index) {
return Container(
child: Text('item: ${newList.elementAt(index)}'),
);
},
),
FloatingActionButton(
child: Icon(
Icons.add,
color: Colors.blue,
),
onPressed: () async {
newList = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FavoriteList(),
),
);
setState(() {});
},
)
],
),
);
}
}
final Set saved = Set();
class FavoriteList extends StatefulWidget {
#override
_FavoriteListState createState() => _FavoriteListState();
}
class _FavoriteListState extends State<FavoriteList> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add to Favorites!'),
centerTitle: true,
backgroundColor: Colors.red),
body: SafeArea(
child: ListView.builder(
itemCount: 53,
itemBuilder: (context, index) {
return CheckboxListTile(
activeColor: Colors.red,
checkColor: Colors.white,
value: saved.contains(index),
onChanged: (val) {
setState(() {
// isChecked = val; // changed
// if(val == true){ // changed
// __saved.add(context); // changed
// } else{ // changed
// __saved.remove(context); // changed
// } // changed
if (val == true) {
saved.add(index);
} else {
saved.remove(index);
}
});
},
title: Row(
children: <Widget>[
//Image.asset('lib/images/${images[index]}'),
SizedBox(
width: 10,
),
Text('nameOfSite[index]'),
],
),
);
},
),
),
floatingActionButton: FloatingActionButton(
foregroundColor: Colors.red,
child: Icon(Icons.check),
onPressed: () {
Navigator.pop<Set>(context, saved);
},
),
);
}
}