flutter Problem: How to update number of items count in cart? - flutter

I implement to add to cart functionality items added into cart successfully but the number of count in the cart badge is not updated when I reload dart page than the number of count updates.can anyone help me?
I implement to add to cart functionality items added into cart successfully but the number of count in the cart badge is not updated when I reload dart page than the number of count updates.can anyone help me?
This is my Homepage.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:badges/badges.dart';
import 'package:hospital/BestDeatProducts/best_deal_product_page.dart';
import 'package:hospital/CartPage/pages/cartPage.dart';
import 'package:hospital/Drawer/dropdown_menu.dart';
import 'package:hospital/FirstSection/carousel.dart';
import 'package:hospital/Drawer/drawercontent.dart';
import 'package:hospital/FloatingActionButton/ConsultWithDoctor/consult_with_doctor.dart';
import 'package:hospital/MedicineCateory/medicine_category_page.dart';
import 'package:hospital/SecondSection/second_page.dart';
import 'package:hospital/ThirdSection/third_page.dart';
import 'package:hospital/TrendingProducts/trending_product_page.dart';
import 'package:hospital/constant.dart';
import 'package:hospital/customApiVariable.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'No Internet/connectivity_provider.dart';
import 'No Internet/no_internet.dart';
import 'package:http/http.dart' as http;
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
SharedPreferences loginData;
// late String username;
Future getUsername() async {
loginData = await SharedPreferences.getInstance();
setState(() {
// print("uname" + uname.toString());
print("dddpppuu1 : responceData_un" +
loginData.getString('responceData_un').toString());
print("dddpppuu2 : responceData_ue" +
loginData.getString('responceData_ue').toString());
print("dddpppuu3 : responceData_status" +
loginData.getString('responceData_status').toString());
String responceData_uid =
loginData.getString('responceData_uid').toString();
fetchData(responceData_uid);
});
}
var response;
var addToCartApi;
#override
void initState() {
// TODO: implement initState
//
super.initState();
Provider.of<ConnectivityProvider>(context, listen: false).startMonitering();
// for loading
getUsername();
}
fetchData(String argResponceData_uid) async {
var api = Uri.parse(
'$ecommerceBaseUrl/addToCartApi.php?a2rTokenKey=$a2rTokenKey&action=addToCartList&uid=${argResponceData_uid}');
print('cartpage' + api.toString());
response = await http.get(api);
print("Carousel" + response.body);
addToCartApi = jsonDecode(response.body);
print('addToCartApi' + addToCartApi['total'].toString());
print('totalPriceAfterOffer' + totalPriceAfterOffer.toString());
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: kGreen,
title: Text(
"BK Arogyam",
style: TextStyle(fontStyle: FontStyle.italic),
),
actions: [
response != null
? Badge(
position: BadgePosition.topEnd(top: 3, end: 18),
animationDuration: Duration(milliseconds: 300),
animationType: BadgeAnimationType.slide,
badgeContent: Text(
addToCartApi['total']['num'].toString(),
style: TextStyle(color: Colors.white),
),
child: IconButton(
icon: Icon(Icons.shopping_cart),
padding: EdgeInsets.only(right: 30.0),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Cartpage()),
);
}),
)
: IconButton(
icon: Icon(Icons.shopping_cart),
// onPressed: () => print("open cart"),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Cartpage()),
);
},
),
DropDownMenu(),
],
),
floatingActionButton: FloatingActionButton(
backgroundColor: kGreen,
onPressed: () => Navigator.push(context,
MaterialPageRoute(builder: (context) => ConsultWithDoctor())),
tooltip: 'Consult With Doctor',
child: Container(
child: Image(
image: AssetImage(
"assets/icons/cwd.png",
),
color: Colors.white,
width: 40,
height: 40,
),
),
),
drawer: Drawer(
child: DrawerContent(),
),
body: pageUI());
}
Widget pageUI() {
return Consumer<ConnectivityProvider>(
builder: (consumerContext, model, child) {
if (model.isOnline != null) {
return model.isOnline
? ListView(
children: [
Carousel(),
SizedBox(
height: 10.0,
),
MedicineCategoryPage(),
SizedBox(
height: 10.0,
),
SecondPage(),
SizedBox(
height: 10.0,
),
ThirdPage(),
SizedBox(
height: 10.0,
),
TrendingProductPage(),
SizedBox(
height: 16.0,
),
BestDealProductPage(),
SizedBox(
height: 10.0,
),
],
)
: NoInternet();
}
return Container(
child: Center(
child: CircularProgressIndicator(),
),
);
},
);
}
}

You can use the change notifier provide by provider package.
And watch the video on how to use, exactly for ur use case search YouTube change notifier provider by the growing developer
Hope it helps 🙂

You can use provider(provider: ^5.0.0) or Getx(get: ^4.1.4) to handle this kind of case.
There are lots of examples are available for GetX and Provider.
If you don't want to use any of them, Then store your cart/badge count to tempCartCount variable(Example: int cartCount = 0) and set it to the badge count instead of "addToCartApi['total']['num'].toString()" , Make sure to setState on update/addCart Item.
Here I provide a simple example of how to update count on appBar.
if you want to change from any other screen make cartCount to global otherwise you can set it local/private.
import 'package:badges/badges.dart';
import 'package:flutter/material.dart';
class UpdateCountExample extends StatefulWidget {
#override
_UpdateCountExampleState createState() => _UpdateCountExampleState();
}
int cartCount = 0;
class _UpdateCountExampleState extends State<UpdateCountExample> {
List<String> cartArray = [];
#override
void initState() {
WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
setState(() {
cartCount = 0;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("App Bar"),
actions: [
Padding(
padding: const EdgeInsets.only(right: 18.0, top: 5.0),
child: Badge(
badgeContent: Text(cartCount.toString()),
child: Icon(Icons.add_shopping_cart),
),
)
],
),
body: Container(
alignment: Alignment.center,
padding: EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"Add item in cart",
textAlign: TextAlign.center,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, decoration: TextDecoration.none, color: Colors.black),
),
SizedBox(
height: 20,
),
InkWell(
onTap: () {
setState(() {
cartArray.add("value ${cartArray.length}");
cartCount = cartArray.length;
});
},
child: Container(
padding: const EdgeInsets.all(10.0),
color: Colors.amber,
child: Text(
"Add Item",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 15, decoration: TextDecoration.none, color: Colors.black),
),
),
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: cartArray.length,
itemBuilder: (context, index) {
return Text(
cartArray[index],
style: TextStyle(fontSize: 20, color: Colors.black),
);
}),
)
],
),
),
);
}
}

I have used StreamBuilder to update cart items instantly.
You can use the code from this post
How to use Streambuilder in flutter

Related

i can't see my images on carousel slider before i hot reload

hello everyone i am new in flutter. i have a problem, when i start the application i cant see my images on carousel but when i hot reload i can see them. I think that if i put if/else condition it might work but i could not do it can some one help me about that?
here are the codes;
import 'dart:convert';
import 'package:carousel_slider/carousel_slider.dart';
import 'package:feedme_start/widgets/Navigation_Drawer_Widget.dart';
import 'package:flutter/material.dart';
// ignore: import_of_legacy_library_into_null_safe
import 'package:flutter_swiper/flutter_swiper.dart';
import 'package:http/http.dart';
import 'model/AnaEkran_modeli.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
final imageList = [];
int ct = imageList.length;
class _MyAppState extends State<MyApp> {
String cevap = "";
late Apianaekran _apianaekran;
late Result _result;
get Index => null;
//"getapidata" adlı future methodda apilerle resimleri çekiyorum sonra imageListe ekliyorum
Future<void> getapidata() async {
String url =
"https://www.mobilonsoft.com/fpsapi/default.aspx?op=application_initialization_customer&firmuid=feedmekktc&device_id=web_20210813180900001&device_platform=4&lang=en";
Response responsee = await get(Uri.parse(url));
if (responsee.statusCode == 200) {
//statusCode 200 oldumu bağlantı siteyle doğru şekilde kuruldu demektir.
Map cevapjson =
jsonDecode(responsee.body); //cevap, json code daki body i alır.
Apianaekran ekran = Apianaekran.fromJson(cevapjson);
ct = ekran.result.sliderImages.length;
print(ct);
int i = 0;
while (i < ct) {
imageList.add(ekran.result.sliderImages[i].imageUrl);
print(ekran.result.sliderImages[i].imageUrl);
i++;
}
} else {
print("bir sorun oluştu");
}
print("resimler başarıyla çekildi");
print(imageList.length);
}
#override
void initState() {
getapidata();
}
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.red,
title: Center(child: Text("FEED ME")),
actions: <Widget>[
IconButton(onPressed: () {}, icon: Icon(Icons.call))
],
),
drawer: NavigationDrawerWidget(),
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Column(
children: [
Container(
constraints: BoxConstraints.expand(height: 200),
child: CarouselSlider(
options: CarouselOptions(
enlargeCenterPage: true,
enableInfiniteScroll: true,
autoPlay: true),
items: imageList
.map((e) => ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Stack(
fit: StackFit.expand,
children: <Widget>[
Image.network(
e,
width: 1050,
height: 350,
fit: BoxFit.cover,
)
],
),
))
.toList())), //imageSlider(context),),
/* Divider(,,
color: Colors.red,
),*/
SizedBox(
height: 75,
),
ElevatedButton.icon(
onPressed: () {
getapidata();
}, //api çekiminin denemesini bu tuşnan yaparım şimdilik
icon: Icon(Icons.add),
label: Text("Yeni Sipariş Ver"),
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.red)),
),
SizedBox(
height: 50,
),
// Text(_anaEkranJsonlar.statusCodeDescription),
SizedBox(
height: 150,
),
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: ElevatedButton.icon(
onPressed: () {},
icon: Icon(Icons.add),
label: Text("Canlı Destek"),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.red[900])),
),
),
SizedBox(
width: 5,
),
Expanded(
child: ElevatedButton.icon(
onPressed: () {},
icon: Icon(Icons.sms),
label: Text("Fırsatlar"),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.red[900])),
),
),
],
),
SizedBox(
height: 30,
),
Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: ElevatedButton.icon(
onPressed: () {},
icon: Icon(Icons.exit_to_app),
label: Text("Giriş"),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.red[900])),
),
),
SizedBox(
width: 5,
),
Expanded(
child: ElevatedButton.icon(
onPressed: () {},
icon: Icon(Icons.person_add),
label: Text("Kayıt Ol"),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Colors.red[900])),
),
),
],
)
],
),
)
/*Swiper(itemCount: imageList.length,
itemBuilder: (context, index) {
return Image.network(imageList[index],/*errorBuilder:
(BuildContext context, Object exception, StackTrace? stackTrace), {return const("resim yüklenemedi")},*/
fit: BoxFit.cover,);
},)*/
),
);
}
}
this is the picture of first start
this one is after i hot reload the code
it has to be like in 2nd pic. can someone help me ?
You need to update the state of your widget inside getapidata after you've loaded all the images:
Future<void> getapidata() async {
String url = "https://www.mobilonsoft.com/fpsapi/default.aspx?op=application_initialization_customer&firmuid=feedmekktc&device_id=web_20210813180900001&device_platform=4&lang=en";
Response responsee = await get(Uri.parse(url));
if (responsee.statusCode == 200) {
// ...
setState(() {});
}
}
The above will already work as expected, but you should consider using a FutureBuilder. Also, you should put
final imageList = [];
int ct = imageList.length;
inside your widget's state, and not in the global scope.

How to Show the Json api data in the dynamic Bar Charts in flutter/

**im trying development Covid 19 app in a flutter.And trying to render a dynamic bar chart in the dashboard of the application. I try to write some codes but this is not going to work to fetching data from API show into it bar dynamic bar charts.
Here are some codes which I tried my best but showing error.
here is my testing application screenshot
enter image description here
enter code here
import 'dart:convert';
import 'dart:convert';
import 'package:NavigationBar/userModel.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'dart:math';
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter_sparkline/flutter_sparkline.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:NavigationBar/userModel.dart';
import 'package:http/http.dart'as http;
class Dashboard extends StatelessWidget {
#override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
}
#override
Widget build(BuildContext context)
{
return MaterialApp(
debugShowCheckedModeBanner: false,
home: HomePage(
),
);
}
class HomePage extends StatefulWidget
{
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage>
{
Map mapResponce;
static List<charts.Series< addcharts, String>> get series => null;
Future fetchdata() async{
http.Response response;
response = await http.get("https://disease.sh/v3/covid-19/all");
if(response.statusCode==200){
setState(() {
mapResponce =json.decode(response.body);
});
}
}
//static var chartdisplay;
//get _getUser => null;
#override
void initState() {
// TODO: implement initState
fetchdata();
super.initState();
}
Widget databody() {
var data =
[
addcharts("val1", mapResponce['v1']),
addcharts("val2", 20),
addcharts("val3", 30),
addcharts("val4", 40),
addcharts("val5", 50),
addcharts("val6", 60),
addcharts("val7", 70),
];
var series = [charts.Series(
domainFn: (addcharts addcharts, _) => addcharts.label,
measureFn: (addcharts addcharts, _) => addcharts.value,
id: 'addcharts',
data: data,
),
];
}
var chartdisplay = charts.BarChart(series,
animationDuration: Duration(microseconds: 2000),
);
Material myItems(IconData icon,String heading,int color){
return Material(
color: Colors.white,
elevation: 14.0,
shadowColor: Colors.grey,
borderRadius: BorderRadius.circular(24.0),
child: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child:
//Text part
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(heading,
style: TextStyle(
color: new Color(color),
fontSize: 20.0
),
),
),
),
Material(
color: new Color(color),
borderRadius: BorderRadius.circular(24.0),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Icon(
icon,
color: Colors.white,
size: 30.0,
),
),
),
],
)
],
),
),
),
);
}
#override
Widget build(BuildContext context)
{
var chartdisplay;
return Scaffold(
appBar: AppBar(
title: Text("Dashboard",
style: TextStyle(
color: Colors.white,
)),
centerTitle:true,
leading: IconButton(icon: Icon(Icons.arrow_back),
onPressed: (){
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomePage(),
));
}
),
),
body:StaggeredGridView.count(
crossAxisCount: 2,
crossAxisSpacing: 12.0,
mainAxisSpacing: 12.0,
padding: EdgeInsets.symmetric(horizontal: 16.0,vertical: 8.0),
children: <Widget>[
myItems(Icons.add_alert,"ALERT",0xfff44336),
myItems(Icons.ad_units,"22.13",0xffed622b),
myItems(Icons.ad_units,"0",0xffed622b),
myItems(Icons.read_more_outlined,"22.13",0xffed622b),
myItems(Icons.date_range,"2/2/2021",0xffed622b),
// FutureBuilder(
// future: _getUser,
// builder: (context,snapshot) {
// if (snapshot.hasData) {
//
// }
//
// else {
// return CircularProgressIndicator();
// }
// },),
databody(),
Expanded(
flex: 3,
child:Container(
padding: EdgeInsets.all(40.0),
height: MediaQuery.of(context).size.height*0.30,
color: Colors.white,
child: chartdisplay,
),
),
Expanded(
flex: 3,
child:Container(
padding: EdgeInsets.all(40.0),
height: MediaQuery.of(context).size.height*0.30,
color: Colors.white,
child: chartdisplay,
),
),
],
staggeredTiles: [
StaggeredTile.extent(2, 130.0),
StaggeredTile.extent(1, 150.0),
StaggeredTile.extent(1, 150.0),
StaggeredTile.extent(1, 150.0),
StaggeredTile.extent(1, 150.0),
StaggeredTile.extent(2, 250.0),
StaggeredTile.extent(2, 250.0),
],
),
);
}
}
// class dashboard extends StatelessWidget {
// #override
// Widget build(BuildContext context) {
// return Container();
// }
//
// }
class addcharts
{
final String label;
final int value;
addcharts(this.label,this.value);
}
Remove this line from this code
Widget build(BuildContext context) {
// TODO: implement build
//throw UnimplementedError(); //this line
}

how to make flutter searchDelagate a separate screen that can be navigated to independently?

i have a page called searchUsersSCreen which is this:
import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:myApp/models/otherUser.dart';
import 'package:myApp/ui/widgets/user_profile.dart';
import 'database.dart';
class SearchUsersScreen extends StatefulWidget {
#override
_SearchUsersScreenState createState() => _SearchUsersScreenState();
}
class _SearchUsersScreenState extends State<SearchUsersScreen> {
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) => showSearch(
context: context,
delegate: SearchUsers(
DatabaseService().fetchUsersInSearch(),
),
));
}
#override
Widget build(BuildContext context) {
return Container(
color: Theme.of(context).primaryColor,
);
}
}
and inside the same dart file is have this searchDelegate :
//Search delegate
class SearchUsers extends SearchDelegate<OtherUser> {
final Stream<QuerySnapshot> otherUser;
final String hashtagSymbol = 'assets/svgs/flaticon/hashtag_symbol.svg';
SearchUsers(this.otherUser);
#override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = '';
},
),
];
}
#override
Widget buildLeading(BuildContext context) {
return Container(
width: 0,
height: 0,
);
}
#override
Widget buildResults(BuildContext context) {
return Container(
width: 0,
height: 0,
color: Theme.of(context).primaryColor,
);
}
#override
Widget buildSuggestions(BuildContext context) {
showUserProfile(String userId) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UserProfileView(
userUid: userId,
)));
}
return StreamBuilder<QuerySnapshot>(
stream: DatabaseService().fetchUsersInSearch(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
final handlesResults = snapshot.data.documents
.where((u) => u['username'].contains(query));
if (!snapshot.hasData) {
return Container(
color: Theme.of(context).primaryColor,
child: Center(
child: Text(
'',
style: TextStyle(
fontSize: 16, color: Theme.of(context).primaryColor),
),
),
);
}
if (handlesResults.length > 0) {
return Container(
color: Theme.of(context).primaryColor,
child: ListView(
children: handlesResults
.map<Widget>((u) => GestureDetector(
child: Padding(
padding: const EdgeInsets.all(0.1),
child: Container(
padding: EdgeInsets.symmetric(vertical: 5),
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
border: Border(
bottom: BorderSide(
width: 0.3, color: Colors.grey[50]))),
child: ListTile(
leading: CircleAvatar(
backgroundColor:
Theme.of(context).primaryColor,
backgroundImage:
NetworkImage(u['userAvatarUrl']),
radius: 20,
),
title: Container(
padding: EdgeInsets.only(left: 10),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(u['username'],
style: TextStyle(
fontSize: 16,
color: Theme.of(context)
.accentColor),
overflow: TextOverflow.ellipsis),
SizedBox(
height: 5,
),
Text(u['name'],
style: TextStyle(
fontSize: 16,
color: Colors.grey[500],
),
overflow: TextOverflow.ellipsis),
],
),
),
trailing: Container(
padding: EdgeInsets.only(left: 10),
height: 43.0,
width: MediaQuery.of(context).size.width / 2,
),
),
),
),
onTap: () {
showUserProfile(u['id']);
},
))
.toList(),
),
);
} else {
return Container(
color: Theme.of(context).primaryColor,
child: Center(
child: Text(
'No results found',
style: TextStyle(
fontSize: 16,
color: Theme.of(context).accentColor,
),
),
),
);
}
});
}
}
i wanted to user the class SearchUsers as a separate screen that i can navigate to independently...but couldn't achieve that as SearchUsers doesn't evaluate to a widget.
so i built SearchUsersScreen statefulWidget and inside it's initState() i called this:
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) => showSearch(
context: context,
delegate: SearchUsers(
DatabaseService().fetchUsersInSearch(),
),
));
}
as to make the search feature starts automatically when the user navigates to SearchUsersScreen.
and i ended up into two problems:
SearchUsers is being displayed in full screen ontop of SearchUsersSCreen (which i don't want this behavior), i want it to be displayed inside of it.
actually its covering the BottomNavigationBar i built for navigation between screens.
after SearchUsers is being displayed (and its doing its job well), when i tap the device back button...i leave SearchUsers and get back to SearchUsersScreen....which is indeed a blank screen.
so to wrap it up...all i want is to use SearchUsers class as a widget that i can navigate to and navigate from independently...thats it.
any help would be much appreciated.
thanks for your time reading.
Instead of trying to create a separate widget SearchUsers, try to create a dialog and show it when anyone wants to search users. You can also use the navigator and the back button in this case and get arguments passed from the next screen to the previous screen.

Why isn't Navigator.pop() refreshing data?

Hi guys I'm trying to build an app with flutter, so I have two screens HomeScreen() and RoutineScreen(). The first one is a Scaffold and in the body has a child Widget (a ListView called RoutinesWidget()) with all the routines. And the second one is to create a routine. The thing is, that when I create the routine, I use a button to pop to the HomeScreen() but it doesn't refresh the ListView (I'm guessing that it's because when I use Navigator.pop() it refreshes the Scaffold but not the child Widget maybe?)
HomeScreen() code here:
import 'package:flutter/material.dart';
import 'package:workout_time/constants.dart';
import 'package:workout_time/Widgets/routines_widget.dart';
import 'package:workout_time/Widgets/statistics_widget.dart';
import 'package:workout_time/Screens/settings_screen.dart';
import 'package:workout_time/Screens/routine_screen.dart';
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
int _selectedIndex = 0;
List<Widget> _views = [
RoutinesWidget(),
StatisticsWidget(),
];
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: kThirdColor,
appBar: AppBar(
leading: Icon(Icons.adb),
title: Text("Workout Time"),
actions: <Widget>[
IconButton(
icon: Icon(Icons.settings),
onPressed: () => Navigator.push(context,
MaterialPageRoute(builder: (context) => SettingsScreen()))),
],
),
body: _views[_selectedIndex],
floatingActionButton: (_selectedIndex == 1)
? null
: FloatingActionButton(
onPressed: () async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RoutineScreen(null)));
setState(() {});
},
child: Icon(
Icons.add,
color: kSecondColor,
size: 30.0,
),
elevation: 15.0,
),
bottomNavigationBar: BottomNavigationBar(
items: <BottomNavigationBarItem>[
bottomItems(Icon(Icons.fitness_center_rounded), "Routines"),
bottomItems(Icon(Icons.leaderboard_rounded), "Statistics"),
],
currentIndex: _selectedIndex,
onTap: (int index) => setState(() => _selectedIndex = index),
),
);
}
}
BottomNavigationBarItem bottomItems(Icon icon, String label) {
return BottomNavigationBarItem(
icon: icon,
label: label,
);
}
RoutinesWidget() code here:
import 'package:flutter/material.dart';
import 'package:workout_time/Services/db_crud_service.dart';
import 'package:workout_time/Screens/routine_screen.dart';
import 'package:workout_time/constants.dart';
import 'package:workout_time/Models/routine_model.dart';
class RoutinesWidget extends StatefulWidget {
#override
_RoutinesWidgetState createState() => _RoutinesWidgetState();
}
class _RoutinesWidgetState extends State<RoutinesWidget> {
DBCRUDService helper;
#override
void initState() {
super.initState();
helper = DBCRUDService();
}
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: helper.getRoutines(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Routine routine = Routine.fromMap(snapshot.data[index]);
return Card(
margin: EdgeInsets.all(1.0),
child: ListTile(
leading: CircleAvatar(
child: Text(
routine.name[0],
style: TextStyle(
color: kThirdOppositeColor,
fontWeight: FontWeight.bold),
),
backgroundColor: kAccentColor,
),
title: Text(routine.name),
subtitle: Text(routine.exercises.join(",")),
trailing: IconButton(
icon: Icon(Icons.delete_rounded),
color: Colors.redAccent,
onPressed: () {
setState(() {
helper.deleteRoutine(routine.id);
});
},
),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RoutineScreen(routine))),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0)),
color: kSecondColor,
);
},
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
);
}
}
RoutineScreen() code here:
import 'package:flutter/material.dart';
import 'package:workout_time/Models/routine_model.dart';
import 'package:workout_time/Widgets/type_card_widget.dart';
import 'package:workout_time/constants.dart';
import 'package:workout_time/Services/db_crud_service.dart';
class RoutineScreen extends StatefulWidget {
final Routine _routine;
RoutineScreen(this._routine);
#override
_RoutineScreenState createState() => _RoutineScreenState();
}
class _RoutineScreenState extends State<RoutineScreen> {
DBCRUDService helper;
final _nameController = TextEditingController();
final _descriptionController = TextEditingController();
bool _type = true;
int _cycles = 1;
int _restBetweenExercises = 15;
int _restBetweenCycles = 60;
#override
void initState() {
super.initState();
helper = DBCRUDService();
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => Navigator.pop(context),
),
title: widget._routine != null
? Text(widget._routine.name)
: Text("Create your routine"),
actions: [
IconButton(
icon: Icon(Icons.done_rounded),
onPressed: createRoutine,
)
],
bottom: TabBar(
tabs: [
Tab(
text: "Configuration",
),
Tab(
text: "Exercises",
),
],
),
),
body: TabBarView(children: [
//_routine == null ? ConfigurationNewRoutine() : Text("WIDGET N° 1"),
ListView(
children: [
Container(
padding: EdgeInsets.all(15.0),
child: Row(
children: [
Text(
"Name:",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(
width: 40.0,
),
Expanded(
child: TextField(
textAlign: TextAlign.center,
controller: _nameController,
),
),
],
),
),
SizedBox(
height: 20.0,
),
Card(
margin: EdgeInsets.all(15.0),
color: kSecondColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: Container(
padding: EdgeInsets.all(15.0),
child: Column(
children: [
Text(
"Type",
style: TextStyle(fontSize: 25.0),
),
Row(
children: [
Expanded(
child: TypeCard(
Icons.double_arrow_rounded,
_type == true ? kFirstColor : kThirdColor,
() => setState(() => _type = true),
"Straight set",
),
),
Expanded(
child: TypeCard(
Icons.replay_rounded,
_type == false ? kFirstColor : kThirdColor,
() => setState(() => _type = false),
"Cycle",
),
),
],
),
],
),
),
),
SizedBox(
height: 20.0,
),
Container(
padding: EdgeInsets.all(15.0),
child: Row(
children: [
Text(
"N° cycles:",
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.bold,
),
),
SizedBox(
width: 40.0,
),
Expanded(
child: Text("Hello"),
),
],
),
),
SizedBox(
height: 20.0,
),
],
),
Text("WIDGET N° 2"),
]),
),
);
}
void createRoutine() {
List<String> _exercises = ["1", "2"];
List<String> _types = ["t", "r"];
List<String> _quantities = ["30", "20"];
Routine routine = Routine({
'name': _nameController.text,
'description': "_description",
'type': _type.toString(),
'cycles': 1,
'numberExercises': 2,
'restBetweenExercises': 15,
'restBetweenCycles': 60,
'exercises': _exercises,
'types': _types,
'quantities': _quantities,
});
setState(() {
helper.createRoutine(routine);
Navigator.pop(context);
});
}
}
Any idea what can I do to make it work? Thank you
Make it simple
use Navigator.pop() twice
so that the current class and old class in also removed
from the stack
and then use Navigator.push()
When you push a new Route, the old one still stays in the stack. The new route just overlaps the old one and forms like a layer above the old one. Then when you pop the new route, it will just remove the layer(new route) and the old route will be displayed as it was before.
Now you must be aware the Navigator.push() is an asynchronous method and returns a Future. How it works is basically when you perform a Navigator.push(), it will push the new route and will wait for it to be popped out. Then when the new route is popped, it returns a value to the old one and that when the future callback will be executed.
Hence the solution you are looking for is add a future callback like this after your Navigator.push() :
Navigator.push(context,
MaterialPageRoute(builder: (context) => SettingsScreen())
).then((value){setState(() {});}); /// A callback which is executed after the new route will be popped. In that callback, you simply call a setState and refresh the page.

Flutter Unhandled Exception: NoSuchMethodError: The getter 'uid' was called on null

First of all, I would like to say I have seen all the previous posts on this error but none of them resolved my issue and that's why I am posting it.
Actually, I have understood the problem but unable to resolve it. So, the below dart file is my HomeScreen().
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:mukti/authentication/firestore_service.dart';
import 'package:mukti/schedule/task.dart';
import 'package:mukti/schedule/taskdata.dart';
import 'package:provider/provider.dart';
import 'add_class.dart';
import 'package:firebase_auth/firebase_auth.dart' as auth;
class HomeScreen extends StatefulWidget {
static final String routeName = 'homeScreen';
final auth.User firebaseUser;
HomeScreen({this.firebaseUser});
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final FirestoreService firestoreService = FirestoreService();
#override
Widget build(BuildContext context) {
print("HomeScreen");
print(widget.firebaseUser);
return Scaffold(
body: SafeArea(
child: SizedBox.expand(
child: Padding(
padding: const EdgeInsets.all(48.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SingleChildScrollView(
child: Container(
width: MediaQuery.of(context).size.width,
height: 450,
color: Colors.yellow[100],
child: generateTaskList(),
),
),
SizedBox(height: 45),
/* Add Class Button */
Center(
child: GestureDetector(
onTap: () {
Navigator.push(
context, MaterialPageRoute(
builder: (context) => AddClass(),
),
);
},
child: Container(
height: 75,
width: 75,
decoration: BoxDecoration(
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(0, 4), //(x,y)
blurRadius: 1.0,
),
],
color: Color(0xFFF9A826),
),
child: Icon(
Icons.add,
size: 35,
color: Colors.white,
),
),
),
),
],
),
),
),
),
);
}
Widget generateTaskList() {
//print("Firebase User : ${widget.firebaseUser.uid}");
Provider.of<TaskData>(context, listen: false).loadTaskList(widget.firebaseUser);
print('List Generated');
var taskListLength = Provider.of<TaskData>(context, listen: false).getTaskListCount();
return Consumer<TaskData>(
builder: (context, taskData, child) => ListView.builder(
itemCount: taskData.taskList.length,
itemBuilder: (context, index) {
print("TaskList");
return Container(
padding: EdgeInsets.all(16.0),
decoration: new BoxDecoration (
borderRadius: BorderRadius.circular(10),
color: Color(0xFFF9A826),
),
child: ListTile(
title: Text(
taskData.taskList[index].description ?? 'default',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
),
),
subtitle: Text(
"${Util.getFormattedDate(taskData.taskList[index].scheduledDateTime)}" ?? 'default',
style: TextStyle(
color: Colors.white54,
),
),
),
);
}
)
);
}
}
class Util {
static String getFormattedDate(DateTime dateTime) {
return new DateFormat("EEE, MMM d, y").format(dateTime);
}
}
Initially, firebaseUser is not null, I have crossed checked it and it is printing the data in the app but when I add more entries from AddClass() and returns to HomeScreen() again, firebaseUser becomes null and no data is shown in the app anymore.
The below code is my AddClass() code:
import 'package:flutter/material.dart';
import 'package:mukti/authentication/authService.dart';
import 'package:mukti/authentication/firestore_service.dart';
import 'package:mukti/schedule/scheduled_date.dart';
import 'package:mukti/schedule/task.dart';
import 'package:mukti/ui_pages/main_screen/timepicker.dart';
import 'package:provider/provider.dart';
import 'package:table_calendar/table_calendar.dart';
import 'package:firebase_auth/firebase_auth.dart' as auth;
import 'home_screen.dart';
class AddClass extends StatefulWidget {
static final String routeName = 'addClass';
#override
_AddClassState createState() => _AddClassState();
}
class _AddClassState extends State<AddClass> {
final FirestoreService firestoreService = FirestoreService();
#override
Widget build(BuildContext context) {
print("Add Class Screen");
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Color(0xFFFFFFE5),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
/* Meeting url TextField Widget */
/* Description TextField Widget */
/* Calender */
/* Add Class Button */
Expanded(
child: GestureDetector(
onTap: () async{
auth.User firebaseUser = await Provider.of<AuthService>(context, listen: false).getUser();
DateTime scheduledDateTime = Provider.of<ScheduledDate>(context, listen: false).scheduledDateTime;
print(scheduledDateTime);
print(firebaseUser);
final task = Task(
link: 'xyz',
isDone: false,
description: 'xyz',
scheduledDateTime: scheduledDateTime,
);
firestoreService.addTask(firebaseUser, task);
print('Task Added');
Navigator.popAndPushNamed(context,
HomeScreen.routeName,
arguments: firebaseUser,
);
},
child: Align(
alignment: FractionalOffset.bottomCenter,
child: Container(
height: 50,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: Color(0xFFF9A826),
),
child: Center(
child: Text(
'SCHEDULE CLASS',
style: Theme.of(context).textTheme.bodyText1.copyWith(
color: Colors.white,
fontWeight: FontWeight.w700,
fontSize: 16,
letterSpacing: 0.5,
),
)
)
),
),
),
),
],
),
),
);
}
}
Actually, I have removed unnecessary codes, so after adding one more class to the database, I return to HomeScreen but this time firebaseUser becomes null, although I am sending it in the argument of the routes HomeScreen is receiving null. This is my problem.
How can I resolve this..?
If anyone needs more information, feel free to ask me.
Thanks