Provider cannot get value - flutter

i am building mobile app using flutter. i try to use provider but it doesn't get the value.
this is the code for class change notifier
class StoreProvider with ChangeNotifier{
UserServices _userServices = UserServices();
StoreServices _storeServices = StoreServices();
User user = FirebaseAuth.instance.currentUser;
String userLocation = "";
String selectedStore;
String selectedStoreId;
getSelectedStore(storeName, storeId){
this.selectedStore = storeName;
this.selectedStoreId = storeId;
notifyListeners();
}
}
this is the code where i call this function
ListView(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
children: snapshot.data.docs.map((DocumentSnapshot document) {
return InkWell(
onTap: (){
_storeData.getSelectedStore(document['shopName'], document['uid']);
pushNewScreenWithRouteSettings(
context,
settings: RouteSettings(name: VendorHomeScreen.id),
screen: VendorHomeScreen(),
withNavBar: true,
pageTransitionAnimation: PageTransitionAnimation.cupertino,
);
},
child: Padding(
padding: const EdgeInsets.only(top: 4, right: 4, left: 4),
child: Container(
width: 120,
child: Column(
children: [
SizedBox(
width: 120,
height: 100,
child: Card(
child: ClipRRect(
borderRadius: BorderRadius.circular(4),
child: Image.network(document['imageUrl'],))),
),
Container(
height: 35,
child: Text(document['shopName'], style: TextStyle(
fontSize: 14, fontWeight: FontWeight.bold,
), maxLines: 2, overflow: TextOverflow.ellipsis,),
),
],
),
),
),
);
}).toList(),
),
this is the code where i want to get the value that i put to the provider
var _store = Provider.of<StoreProvider>(context);
return Scaffold(
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return [
SliverAppBar(
iconTheme: IconThemeData(
color: Colors.white,
),
actions: [
IconButton(
onPressed: () {},
icon: Icon(CupertinoIcons.search),
)
],
title: Text(
**//this is the error**
**//this is the error**
**//this is the error**
**//this is the error**
**//this is the error**
**_store.selectedStoreId,**
style:
TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
),
)
];
},
body: Center(
child: Text('vendor screen'),
),
));
and this is the main file
void main() async {
Provider.debugCheckInvalidValueType = null;
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => AuthProvider()),
ChangeNotifierProvider(create: (_) => StoreProvider()),
],
child: MyApp(),
));
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(primaryColor: Colors.lightBlueAccent, fontFamily: 'Lato'),
initialRoute: SplashScreen.id,
routes: {
SplashScreen.id: (context) => SplashScreen(),
LoginPage.id: (context) => LoginPage(),
SignupPage.id: (context) => SignupPage(),
HomePage.id: (context) => HomePage(),
ResetPassword.id: (context) => ResetPassword(),
MainScreen.id: (context)=> MainScreen(),
VendorHomeScreen.id: (context) => VendorHomeScreen(),
},
);
}
}
i always get 'a non null A non-null String must be provided to a Text widget.'
i think the problem is when i put the value in the change notifier class and i try to get the value in other class, the value is null.
does anyone know what is the mistake??
thank you

Related

Flutter/Dart - Text value not showing correctly

I am trying to create a shopping cart using provider and display the number of items currently in the cart on my homepage. When I create my cart icon with a text widget overlaid, the value being shown does not reflect the number of items in the cart.
Here is my code:
class OurShoppingBasketIcon extends StatelessWidget {
const OurShoppingBasketIcon({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.center,
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => ShoppingBasketScreen()),
);
},
child: Stack(
children: <Widget>[
new Icon(
Icons.shopping_cart_outlined,
color: Colors.white,
),
new Positioned(
right: 0,
child: new Container(
padding: EdgeInsets.all(1),
decoration: new BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(6),
),
constraints: BoxConstraints(
minWidth: 12,
minHeight: 12,
),
child: Text(
context.read<ShoppingBasket>().items.length.toString(),
style: new TextStyle(
color: Colors.white,
fontSize: 8,
),
textAlign: TextAlign.center,
),
),
)
],
),
),
);
}
}
This is where the icon is implemented:
class OurHomePage extends StatefulWidget {
#override
_OurHomePageState createState() => _OurHomePageState();
}
class _OurHomePageState extends State<OurHomePage> {
#override
Widget build(BuildContext context) {
return Consumer<OurUser>(
builder: (_, user, __) {
return ChangeNotifierProvider<SignInViewModel>(
create: (_) => SignInViewModel(context.read),
builder: (_, child) {
return Scaffold(
appBar: AppBar(
title: Text("My app"),
actions: [
OurShoppingBasketIcon(),
IconButton(
icon: Icon(
Icons.logout,
color: Colors.white,
),
onPressed: () {
context.read<FirebaseAuthService>().signOut();
},
),
],
),
);
},
);
},
);
}
}
There are 2 items in the cart as of writing this:
But the icon on the homepage does not change:
Here is my main.dart:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
MultiProvider(
providers: [
Provider(
create: (_) => FirebaseAuthService(),
),
StreamProvider<OurUser>(
create: (context) =>
context.read<FirebaseAuthService>().onAuthStateChanged),
ChangeNotifierProvider.value(
value: ShoppingBasket(),
),
],
child: MaterialApp(theme: OurTheme().buildTheme(), home: OurHomePage()),
),
);
}
perhaps if you watch for the value it will be updated dynamically:
context.watch<ShoppingBasket>().items.length.toString(), //<-- watch instead of read
The OurHomePage needs to be wrapped in the Provider<ShoppingBasket>.
return Provider<ShoppingBasket>(
create: (context) => ShoppingBasket(),
child: Consumer<OurUser>(
builder: (_, user, __) {
return ChangeNotifierProvider<SignInViewModel>(
create: (_) => SignInViewModel(context.read),
builder: (_, child) {
return Scaffold(
appBar: AppBar(
title: Text("My app"),
actions: [
OurShoppingBasketIcon(),
IconButton(
icon: Icon(
Icons.logout,
color: Colors.white,
),
onPressed: () {
context.read<FirebaseAuthService>().signOut();
},
),
],
),
),
);
},
);
I forgot to NotifyListeners() in my Change Notifier class:
class ShoppingBasket extends ChangeNotifier {
Map<String, SingleBasketItem> _items = {};
Map<String, SingleBasketItem> get items {
return {..._items};
}
void addItem(String id) {
_items.putIfAbsent(
id,
() => SingleBasketItem(id),
);
notifyListeners(); //HERE
}

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 Provider Error: The following ProviderNotFoundException was thrown building HomePage(dirty, state: flutter: _HomePageState#fb424):

My code was actually working and is currently working with the app built from the previous version of flutter. I built it again using the same code but with the Flutter 1.22 upgrade and its causing error now on Provider. Since, the code actually worked, I can't seem to figure out why it is throwing an error.
Here is my code:
The file or the error causing widget according to flutter:
'''
class HomePage extends StatefulWidget {
static final String id = 'home_page';
final String currentUserId;
HomePage({this.currentUserId});
#override
_HomePageState createState() => _HomePageState();
}
CategoryProvider categoryProvider;
ProductProvider productProvider;
class _HomePageState extends State<HomePage> {
// variables
double height, width;
bool homeColor = true;
bool checkoutColor = false;
bool aboutColor = false;
bool contactUsColor = false;
bool profileColor = false;
MediaQueryData mediaQuery;
TextEditingController searchTextEditingController = TextEditingController();
//category each tile change to Service
Widget _buildCategoryProduct({String name, String image, int color}) {
return Container(
child: Column(
children: <Widget>[
Container(
height: 50,
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
boxShadow: shadowList,
color: Colors.white,
borderRadius: BorderRadius.circular(10)),
// maxRadius: height * 0.1 / 2.1,
// backgroundColor: Colors.white,
child: Image(
image:
/// changed
AssetImage('images/category/$image'),
),
),
Text(
name,
style: GoogleFonts.raleway(
fontSize: 12,
fontWeight: FontWeight.bold,
letterSpacing: 1.0,
textStyle: TextStyle(color: Colors.black),
),
),
],
),
);
}
// firebase auth drawer details
/// look into it after
Widget _buildUserAccountsDrawerHeader() {
List<UserModel> userModel = productProvider.userModelList;
return Column(
children: userModel.map((e) {
return UserAccountsDrawerHeader(
accountName: Text(
e.userName,
style: TextStyle(color: Colors.black),
),
currentAccountPicture: CircleAvatar(
backgroundColor: Colors.white,
backgroundImage: e.userImage == null
? AssetImage("images/userImage.png")
: NetworkImage(e.userImage),
),
decoration: BoxDecoration(color: Color(0xfff2f2f2)),
accountEmail: Text(e.userEmail, style: TextStyle(color: Colors.black)),
);
}).toList());
}
//build drawer left side/sidebar
Widget _buildMyDrawer() {
return Drawer(
child: ListView(
children: <Widget>[
_buildUserAccountsDrawerHeader(),
ListTile(
selected: homeColor,
onTap: () {
setState(() {
homeColor = true;
contactUsColor = false;
checkoutColor = false;
aboutColor = false;
profileColor = false;
});
},
leading: Icon(Icons.home),
title: Text("Home"),
),
ListTile(
selected: checkoutColor,
onTap: () {
setState(() {
checkoutColor = true;
contactUsColor = false;
homeColor = false;
profileColor = false;
aboutColor = false;
});
// Navigator.of(context).pushReplacement(
// MaterialPageRoute(builder: (ctx) => CheckOut()));
},
leading: Icon(Icons.shopping_cart),
title: Text("Checkout"),
),
ListTile(
selected: aboutColor,
onTap: () {
setState(() {
aboutColor = true;
contactUsColor = false;
homeColor = false;
profileColor = false;
checkoutColor = false;
});
// Navigator.of(context).pushReplacement(
// MaterialPageRoute(builder: (ctx) => About()));
},
leading: Icon(Icons.info),
title: Text("About"),
),
ListTile(
selected: profileColor,
onTap: () {
setState(() {
aboutColor = false;
contactUsColor = false;
homeColor = false;
profileColor = true;
checkoutColor = false;
});
// Navigator.of(context).pushReplacement(
// MaterialPageRoute(
// builder: (ctx) => ProfileScreen(),
// ),
// );
},
leading: Icon(Icons.info),
title: Text("Profile"),
),
ListTile(
selected: contactUsColor,
onTap: () {
setState(() {
contactUsColor = true;
checkoutColor = false;
profileColor = false;
homeColor = false;
aboutColor = false;
});
// Navigator.of(context).pushReplacement(
// MaterialPageRoute(builder: (ctx) => ContactUs()));
},
leading: Icon(Icons.phone),
title: Text("Contant Us"),
),
ListTile(
onTap: () {
FirebaseAuth.instance.signOut();
},
leading: Icon(Icons.exit_to_app),
title: Text("Logout"),
),
],
),
);
}
/// carousel on top/ change images ^^finalized
Widget _buildImageSlider() {
return Container(
height: 200,
child: Carousel(
borderRadius: true,
radius: Radius.circular(20),
autoplay: true,
autoplayDuration: Duration(seconds: 10),
showIndicator: false,
images: [
// change it up to more approp
AssetImage('images/banner2.jpg'),
AssetImage('images/banner1.jpg'),
AssetImage('images/banner4.jpg'),
],
),
);
}
// build category/services row """"
Widget _buildCategory() {
return Column(
children: <Widget>[
Container(
height: 40,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"SERVICES",
style: GoogleFonts.caveat(
fontSize: 20,
fontWeight: FontWeight.bold,
letterSpacing: 3.0,
textStyle: TextStyle(color: Colors.black),
),
),
],
),
),
Container(
height: 70,
// change new
child: ListView(
scrollDirection: Axis.horizontal,
children: <Widget>[
Row(
children: <Widget>[
// each Service icon
_buildHairIcon(),
SizedBox(width: 20),
_buildWaxIcon(),
SizedBox(width: 20),
_buildPedicureIcon(),
SizedBox(width: 20),
_buildManicureIcon(),
SizedBox(width: 20),
_buildFacialIcon(),
],
),
],
),
),
],
);
}
// row of featured and archives view more
Widget _buildNewAchives() {
final Orientation orientation = MediaQuery.of(context).orientation;
return Container(
/// look into it
height: 500,
child: GridView.count(
crossAxisCount: orientation == Orientation.portrait ? 2 : 3,
childAspectRatio: orientation == Orientation.portrait ? 0.8 : 0.9,
children: productProvider.getHomeAchiveList.map((e) {
return GestureDetector(
onTap: () {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
builder: (ctx) => DetailScreen(
userId: widget.currentUserId,
hairdresserId: e.id,
image: e.image,
rating: e.rating,
name: e.name,
surname: e.surname,
description: e.description,
city: e.city,
waxPrice: e.waxPrice,
facialPrice: e.facialPrice,
manicurePrice: e.manicurePrice,
pedicurePrice: e.pedicurePrice,
hairPrice: e.hairPrice,
),
),
);
},
child: SingleProduct(
image: e.image, rating: e.rating, name: e.name, city: e.city),
);
}).toList(),
),
);
}
// row of featured and archives view more
Widget _buildRow() {
List<Product> newAchivesProduct = productProvider.getNewAchiesList;
return Container(
height: height * 0.1 - 30,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"FEATURED ",
style: GoogleFonts.caveat(
fontSize: 20,
fontWeight: FontWeight.bold,
letterSpacing: 3.0,
textStyle: TextStyle(color: Colors.black),
),
),
GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (ctx) => ListProduct(
userId: widget.currentUserId,
name: "Featured",
isCategory: false,
snapShot: newAchivesProduct,
),
),
);
},
child: Text(
"View all",
style: GoogleFonts.raleway(
fontSize: 15,
fontWeight: FontWeight.bold,
letterSpacing: 1.0,
textStyle: TextStyle(color: Colors.black),
),
),
)
],
),
],
),
);
}
final GlobalKey<ScaffoldState> _key = GlobalKey<ScaffoldState>();
// to get from online firebase database//change names
void getCallAllFunction() {
categoryProvider.getWaxData();
categoryProvider.getHairData();
categoryProvider.getPedicureData();
categoryProvider.getManicureData();
categoryProvider.getFacialData();
categoryProvider.getHairIconData();
productProvider.getNewAchiveData();
productProvider.getFeatureData();
productProvider.getHomeFeatureData();
productProvider.getHomeAchiveData();
categoryProvider.getWaxIcon();
categoryProvider.getPedicureIconData();
categoryProvider.getManicureIconData();
categoryProvider.getFacialIconData();
// productProvider.getUserData();
}
#override
Widget build(BuildContext context) {
//from models product= hairdresser data
categoryProvider = Provider.of<CategoryProvider>(context);
productProvider = Provider.of<ProductProvider>(context);
final String currentUserId = Provider.of<UserData>(context).currentUserId;
getCallAllFunction();
height = MediaQuery.of(context).size.height;
width = MediaQuery.of(context).size.width;
return Scaffold(
key: _key,
drawer: _buildMyDrawer(),
// bottomNavigationBar: BottomNavBar(),
appBar: AppBar(
toolbarOpacity: 0,
shape: RoundedRectangleBorder(),
// search field
title: Text(
'The Mob',
style: TextStyle(
color: Colors.white,
fontFamily: 'Billabong',
fontSize: 35.0,
),
),
elevation: 0.0,
backgroundColor: Colors.blueGrey,
leading: IconButton(
icon: SvgPicture.asset("images/menu.svg"),
onPressed: () {
_key.currentState.openDrawer();
},
),
actions: <Widget>[
NotificationButton(),
],
),
body: Container(
height: double.infinity,
width: double.infinity,
margin: EdgeInsets.symmetric(horizontal: 20),
child: ListView(
scrollDirection: Axis.vertical,
children: <Widget>[
SizedBox(height: 5),
Container(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
_buildImageSlider(),
_buildCategory(),
_buildRow(),
_buildNewAchives(),
],
),
),
],
),
),
);
}
}
'''
I have provided the multi providers in the main while with child as MaterialApp. Hence the main file looks like this:
'''
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => ServicesNotifier(),
),
ChangeNotifierProvider(
create: (context) => HairdresserData(),
),
ChangeNotifierProvider(
create: (context) => ServicesNotifier(),
),
ChangeNotifierProvider<CategoryProvider>(
create: (context) => CategoryProvider(),
),
ChangeNotifierProvider<ProductProvider>(
create: (context) => ProductProvider(),
),
ChangeNotifierProvider(
create: (context) => UserData(),
),
],
child: MyApp(),
),
);
}
'''
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: OnboardingScreen(),
routes: {
// '/a': (_) => Authenticate(),
SignInScreen.id: (context) => SignInScreen(),
RegisterScreen.id: (context) => RegisterScreen(),
LoginScreen.id: (context) => LoginScreen(),
SignupScreen.id: (context) => SignupScreen(),
'/b': (_) => Customer(),
'/c': (_) => Hairdresser(),
'/d': (_) => Choose(),
'/e': (_) => IndicatorScreen(),
},
);
}
}
The error is as follows:
The following ProviderNotFoundException was thrown building HomePage(dirty, state:
flutter: _HomePageState#fb424):
flutter: Error: Could not find the correct Provider<CategoryProvider> above this HomePage Widget
flutter:
flutter: This likely happens because you used a `BuildContext` that does not include the provider
flutter: of your choice. There are a few common scenarios:
flutter:
flutter: - The provider you are trying to read is in a different route.
flutter:
flutter: Providers are "scoped". So if you insert of provider inside a route, then
flutter: other routes will not be able to access that provider.
flutter:
flutter: - You used a `BuildContext` that is an ancestor of the provider you are trying to read.
flutter:
flutter: Make sure that HomePage is under your MultiProvider/Provider<CategoryProvider>.
flutter: This usually happen when you are creating a provider and trying to read it immediately.
flutter:
flutter: For example, instead of:
flutter:
flutter: ```
flutter: Widget build(BuildContext context) {
flutter: return Provider<Example>(
flutter: create: (_) => Example(),
flutter: // Will throw a ProviderNotFoundError, because `context` is associated
flutter: // to the widget that is the parent of `Provider<Example>`
flutter: child: Text(context.watch<Example>()),
flutter: ),
flutter: }
flutter: ```
flutter:
flutter: consider using `builder` like so:
flutter: ```
flutter: Widget build(BuildContext context) {
flutter: return Provider<Example>(
flutter: create: (_) => Example(),
flutter: // we use `builder` to obtain a new `BuildContext` that has access to the provider
flutter: builder: (context) {
flutter: // No longer throws
flutter: return Text(context.watch<Example>()),
flutter: }
flutter: ),
flutter: }
flutter: ```
I simply resolve this issue by move all the files to lib instead of making provider directory to lib because provider did not able to find another file that we want to use. It works for me.

Flutter Mobx multiple store not updating value in observer

I am using Mobx in my flutter application. I have multiple store. When I am trying to update some value in a store it is updating but not reflecting on UI.
main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
Provider<LocationStore>(create: (_) => LocationStore()),
Provider<UserStore>(create: (_) => UserStore()),
Provider<RideStore>(create: (_) => RideStore()),
],
child: MaterialApp(
title: 'FLutter APp',
theme: myTheme(),
debugShowCheckedModeBanner: false,
// home: HomePage(
// title: 'Live Location'
// ),
initialRoute: WelcomeScreen.id,
routes: {
HomePage.id: (context) => HomePage(title: 'Home',),
ProfileScreen.id: (context) => ProfileScreen(),
WelcomeScreen.id: (context) => WelcomeScreen(),
RegistrationScreen.id: (context) => RegistrationScreen(),
LoginScreen.id: (context) => LoginScreen(),
FeedScreen.id: (context) => FeedScreen(),
RecordTrackScreen.id: (context) => RecordTrackScreen(),
SaveActivityScreen.id: (context) => SaveActivityScreen(),
UserProfileScreen.id: (context) => UserProfileScreen(),
RideDetailsScreen.id: (context) => RideDetailsScreen(),
StatsScreen.id: (context) => StatsScreen(),
FindInviteScreen.id: (context) => FindInviteScreen(),
CommentsScreen.id: (context) => CommentsScreen(),
},
),
);
}
}
screen
#override
Widget build(BuildContext context) {
final store = Provider.of<LocationStore>(context);
final rideStore = Provider.of<RideStore>(context);
final userStore = Provider.of<UserStore>(context);
return Scaffold(
appBar: AppBar(
title: Text('Record'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.info_outline),
onPressed: () {},
)
],
),
body: Observer(
builder: (_) => SingleChildScrollView(
child: Center(
child: Column(
children: <Widget>[
// Text('isPermitted - ${isPermitted}'),
Container(
child: isPermitted != null && isPermitted ? WeatherMainWidget() : Text(''),
height: (MediaQuery.of(context).size.height - 50.0) * 0.4,
),
Container(
height: (MediaQuery.of(context).size.height - 50.0) * 0.45,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
// Text('rideStore.getIsStarted - ${rideStore.getIsStarted} - $_isRunning'),
// if (rideStore.isStarted)
Divider(
indent: 10.0,
endIndent: 10.0,
thickness: 1.0,
color: color8,
),
Observer(
builder: (_) => Row(
children: [
Text('${rideStore.getSport.name}'),
Expanded(
flex: 1,
child: CustomIconButton(
iconData: rideStore.getSport.icon,
iconColor: Theme.of(context).primaryColor,
bgColor: Colors.transparent,
onPress: () {
SportBottomSheet(context, rideStore);
},
),
),
],
),
),
Container(
child: Visibility(
child: RecordTrackScreen(),
visible: rideStore.isStarted,
),
),
if (!rideStore.isStarted)
Container(
width: 70.0,
height: 70.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(50.0),),
color: Theme.of(context).primaryColor,
),
child: Visibility(
visible: !rideStore.isStarted,
child: CustomIconButton(
iconData: Icons.play_arrow,
iconColor: Colors.white,
iconSize: 35.0,
onPress: () {
print('dsdsadsadsad');
startTrip(store, rideStore, userStore);
},
),
),
),
],
),
),
// ListenLocationWidget()
],
),
),
),
),
);
}
Widget SportBottomSheet(BuildContext context, RideStore rideStore) {
showModalBottomSheet(context: context, builder: (BuildContext bc) {
return Container(
color: Colors.white,
child: ListView.builder(itemCount: 2, itemBuilder: (ctx, index) {
final sport = rideStore.sports[index];
return GestureDetector(
child: ListTile(
leading: Icon(sport.icon, size: 30.0, color: Colors.black,),
title: Text(sport.name, style: TextStyle(
fontSize: 20.0,
color: Colors.black
),),
onTap: () {
print('SportBottomSheet $sport');
rideStore.selectedSport = new Sport(
sport.icon,
sport.name
);
rideStore.recentSport = rideStore.recentSport;
Navigator.pop(context);
print('sport ${rideStore.getSport.name}');
},
),
);
}),
);
});
}
ride store
class Sport{
final IconData icon;
final String name;
Sport(this.icon, this.name);
}
List<Sport> sports = [
new Sport(Icons.directions_walk_outlined, 'Walk'),
new Sport(Icons.motorcycle, 'Ride'),
];
#observable
Sport recentSport;
#observable
Sport selectedSport;
#computed
Sport get getSport {
if (selectedSport != null)
return selectedSport;
if (recentSport != null)
return recentSport;
return sports[0];
}
When I am checking getSport value in onTap method it is showing selected value but it is not updating on UI.
Thanks
Try changing your #computed to #action
#action
Sport get getSport {
if (selectedSport != null)
return selectedSport;
if (recentSport != null)
return recentSport;
return sports[0];
}
or maybe use ObservableList or ObservableFuture
Use ObservableList like this
#observable
ObservableList<Sport> sports =[Sport(Icons.directions_walk_outlined, 'Walk'), new Sport(Icons.motorcycle, 'Ride'),];

How to validate the current date in (dd-mm) format with the passcode

I'm trying to build two screens where:
The first screen has a Pincode textfield when the user enters the current date in (dd-mm) format for eg: if today's date is 24-07, the user enters 2407, then it should navigate to another page i.e., second screen
First Screen: Passcode.dart
import 'package:flutter/material.dart';
import 'package:flutter_course/HomePage.dart';
//import 'package:pin_entry_text_field/pin_entry_text_field.dart';
import 'package:pin_code_text_field/pin_code_text_field.dart';
import 'package:intl/intl.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: homePage(),
));
}
}
class homePage extends StatefulWidget {
#override
_homePageState createState() => _homePageState();
}
class _homePageState extends State<homePage> {
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Stack(children: <Widget>[
Center(
child: Image.asset(
"assets/passcode.jpeg",
width: size.width,
height: size.height,
fit: BoxFit.fill,
),
),
Column(
children: <Widget>[
// SizedBox(height:200,),
// SizedBox(width: 300),
Padding(
padding: EdgeInsets.only(left: 460, top: 150),
child: Text("ENTER PASSCODE",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 38.0,
color: Colors.black)),
),
SizedBox(height: 30),
Padding(
padding: EdgeInsets.only(left: 460),
child: PinCodeTextField(
autofocus: false,
pinTextStyle: TextStyle(
color: Colors.black,
fontSize: 40,
fontWeight: FontWeight.bold),
hideCharacter: true,
maskCharacter: "*",
// highlight: true,
// highlightColor: Colors.blue,
defaultBorderColor: Colors.black,
hasTextBorderColor: Colors.white,
hasError: true,
errorBorderColor: Colors.red,
//onTextChanged: (String)=>func(context),
onDone: (String) => func(context),
),
),
],
)
]);
}
}
void func(context) {
var now = new DateTime.now();
var formatter = new DateFormat('MMMMd');
var formatted = formatter.format(now);
debugPrint(formatted);
if (String == formatted) {
Navigator.push(
context, MaterialPageRoute(builder: (context) => HomePage()));
}
}
Second Screen :HomePage.dart
import 'package:flutter/material.dart';
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return DefaultTabController(length: 2,child:Scaffold(
drawer: Drawer(
child: Column(
children: <Widget>[
AppBar(
automaticallyImplyLeading: false,
title: Text('Choose'),
backgroundColor:Color(0xffedac51),
),
ListTile(
title: Text('Devices'),
onTap: () {
// Navigator.pushReplacement(
// context,
// MaterialPageRoute(
// builder: (BuildContext context) =>
// ProductsPage()));
},
),
ListTile(
title: Text('Allotted Devices'),
onTap: () {
// Navigator.pushReplacement(
// context,
// MaterialPageRoute(
// builder: (BuildContext context) =>
// ProductsPage()));
},
),
ListTile(
title: Text('Assign Devices'),
onTap: () {
// Navigator.pushReplacement(
// context,
// MaterialPageRoute(
// builder: (BuildContext context) =>
// ProductsPage()));
},
)
],
),
),
appBar: AppBar(
title: Text('Home'),
backgroundColor:Color(0xffedac51) ,
),
body: HomeBody()
)
);}
}
class HomeBody extends StatelessWidget{
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Stack(
children: <Widget>[
Center(
child: new Image.asset(
'assets/passcode.jpeg',
width: size.width,
height: size.height,
fit: BoxFit.fill,
),
),
Padding(
padding: EdgeInsets.only(top: 200, left: 500),
child: Column(
children: <Widget>[
Text("Let\'s Get Started!",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 38.0,
color: Colors.white)),
],
)),
],
);
}
}
When the passcode is entered as the current date in ddmm format, then it should navigate to the next screen
Not quite sure what you're trying to achieve, but something simple like this should do the trick:
DateTime today = DateTime.now();
String day, month, passCode;
if(today.day < 10){
day = "0" + today.day.toString();
} else {
day = today.day.toString();
}
if(today.month < 10){
month = "0" + today.month.toString();
} else {
month = today.month.toString();
}
passCode = day + month;