I am trying to access userModel.uid from UserProvider inside the ItemProvider so it can load _savedItems.
However, when I call loadUserSavedItems(), _userId is null.
Here is my main.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'providers/user.dart';
import 'providers/item.dart';
import 'screens/home.dart';
void main() {
Provider.debugCheckInvalidValueType = null;
WidgetsFlutterBinding.ensureInitialized();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider<UserProvider>(
create: (_) => UserProvider.initialize()),
ChangeNotifierProxyProvider<UserProvider, ItemProvider>(
create: (_) => ItemProvider(),
update: (_, userProvider, itemProvider) => itemProvider,
),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.white,
primaryTextTheme: TextTheme(
headline6: TextStyle(color: Colors.black),
),
),
home: Home(),
),
),
);
}
UserProvider.dart
import 'models/user.dart';
import 'services/user.dart';
enum Status { Uninitialized, Authenticated, Authenticating, Unauthenticated }
class UserProvider extends ChangeNotifier {
FirebaseAuth _auth;
FirebaseUser _user;
Status _status = Status.Uninitialized;
Firestore _firestore = Firestore.instance;
UserServices _userServicse = UserServices();
UserModel _userModel;
// getter
UserModel get userModel => _userModel;
Status get status => _status;
FirebaseUser get user => _user;
UserProvider.initialize() : _auth = FirebaseAuth.instance {
_auth.onAuthStateChanged.listen(_onStateChanged);
notifyListeners();
}
Future<void> _onStateChanged(FirebaseUser firebaseUser) async {
if (firebaseUser == null) {
_status = Status.Unauthenticated;
} else {
_user = firebaseUser;
_status = Status.Authenticated;
_userModel = await _userServicse.getUserById(user.uid);
}
notifyListeners();
}
Future<bool> signIn() async {
bool retVal = false;
try {
_status = Status.Authenticating;
notifyListeners();
AuthResult _authResult = await _auth.signInWithEmailAndPassword(
email: email.text.trim(), password: password.text.trim());
if (_authResult.user != null) {
retVal = true;
}
} catch (e) {
_status = Status.Unauthenticated;
notifyListeners();
print(e.toString());
}
return retVal;
}
}
ItemProvider.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/foundation.dart';
import 'models/item.dart';
import 'providers/user.dart';
import 'services/item.dart';
class ItemProvider extends ChangeNotifier {
ItemProvider({UserProvider userProvider}) : _userProvider = userProvider;
UserProvider _userProvider;
final databaseReference = Firestore.instance;
ItemServices _itemServices = ItemServices();
List<Item> _items = [];
List<Item> _savedItems = [];
String _userId;
// getter
List<Item> get items => _items;
List<Item> get savedItems => _savedItems;
String get userId => _userId;
UserProvider get userProvider => _userProvider;
//get the items to load when the app is initiated
ItemProvider.initialize() {
loadAllActiveItems();
if (_userProvider.status == Status.Authenticated) {
loadUserSavedItems();
}
}
//get active items from DB
loadAllActiveItems() async {
_items = await _itemServices.getBatchOfActiveItems();
notifyListeners();
}
//get user saved items from DB
loadUserSavedItems() async {
_userId = userProvider.userModel.uid;
_savedItems = await _itemServices.getUserSavedItems(userId);
notifyListeners();
}
}
Can someone help me, I am not quite sure what I am missing, can't userModel object/properties in ItemProvider.dart when implemented as ChangeNotifierProxyProvider.
I finally found a way around, maybe not the best but it worked.
Inside ItemProvider created updates() to receive the userId from
void updates(String userId, Status status) {
this._userId = userId;
}
And then made the changes in main.dart to pass the userId from ChangeNotifierProxyProvider.
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'providers/user.dart';
import 'providers/item.dart';
import 'screens/home.dart';
void main() {
Provider.debugCheckInvalidValueType = null;
WidgetsFlutterBinding.ensureInitialized();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider<UserProvider>(
create: (_) => UserProvider.initialize()),
ChangeNotifierProxyProvider<UserProvider, ItemProvider>(
create: (_) => ItemProvider(),
update: (_, userProvider, itemProvider) => itemProvider
..updates(
userProvider.user != null ? userProvider.user.uid : ''),
),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.white,
primaryTextTheme: TextTheme(
headline6: TextStyle(color: Colors.black),
),
),
home: Home(),
),
),
);
}
Happy to hear what others have done as well.
Related
I am using flutter localizations for changing language in my flutter app. I want to change my app's language in real time and have implemented logic for that. Now, I want that when user closes app and restarts it, he gets same language he chose before, i.e. language should not set back to default after user closes the app. For this purpose, I am using shared preferences to save the code of language that user selected, and now I can't retrieve it in the beginning of the app. Please help!
locale_provider.dart:
import 'package:flutter/material.dart';
import 'package:myapp/l10n/l10n.dart';
import 'package:shared_preferences/shared_preferences.dart';
class LocaleProvider extends ChangeNotifier {
Locale? _locale = const Locale('en');
Locale? get locale => _locale;
void setLocale(Locale locale) {
if (!L10n.all.contains(locale)) return;
_locale = locale;
notifyListeners();
//setLocaleSettings(locale);
}
void clearLocale() {
_locale = null;
notifyListeners();
}
void changeLocaleSettings(Locale newLocale) async {
if(newLocale == Locale('en')) {
_locale = Locale('en');
} else if(newLocale==Locale('uk')){
_locale = Locale('uk');
} else if(newLocale==Locale('ru')){
_locale = Locale('ru');
}
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString("code", _locale?.countryCode??"en");
notifyListeners();
}
Future getLocaleFromSettings() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String code = prefs.getString("code")??"en";
Locale newLocale = Locale(code);
if(newLocale == Locale('en')) {
_locale = Locale('en');
} else if(newLocale==Locale('uk')){
_locale = Locale('uk');
} else if(newLocale==Locale('ru')){
_locale = Locale('ru');
}
}
}
In my language selection dropdown, I am changing language like this:
class LanguagePickerWidget extends StatelessWidget {
const LanguagePickerWidget({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final provider = Provider.of<LocaleProvider>(context);
final locale1 = provider.locale ?? const Locale('en');
return DropdownButtonHideUnderline(
child: SizedBox(
width: 15,
child: Theme(
data: Theme.of(context).copyWith(
canvasColor: Colors.green.shade300,
),
child: DropdownButton(
borderRadius:BorderRadius.circular(12),
isExpanded: true,
itemHeight: null,
value: locale1,
icon: Container(
//width: 10.0
),
items: L10n.all.map(
(locale) {
final flag = L10n.getFlag(locale.languageCode);
return DropdownMenuItem(
child: Align(
alignment: Alignment.center,
child: Text(
flag,
style: const TextStyle(fontSize: 22.0),
),
),
value: locale,
onTap: () {
final provider = Provider.of<LocaleProvider>(context, listen: false);
provider.setLocale(locale);
provider.changeLocaleSettings(locale);
print(locale);
},
);
},
).toList(),
onChanged: (_) {},
),
),
),
);
}
}
In main.dart:
class MyApp extends StatelessWidget {
MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) => ChangeNotifierProvider(
create: (context) => LocaleProvider(),
builder: (context, child) {
final provider = Provider.of<LocaleProvider>(context);
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
scaffoldBackgroundColor: Colors.lightGreen[100],
primarySwatch: Colors.green,
),
//locale: provider.locale,
supportedLocales: L10n.all,
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
home: const HomePage(),
);
});
}
It works pretty well for changing the language in runtime..
And now I don't understand how to retrieve and set the previously selected language (from shared preferences)? Please help!
Create a default constructor for LocaleProvider class and put this code inside it
LocaleProvider(){
Fututre.delayed(Duration.zero, getLocaleFromSettings);
}
and at the end of your function getLocaleFromSettings(), call notifyListeners();
the reason to use FutureBuilder is that if you called notifyListeners while building frame is processing it will give you an error, so adding some delay to prevent rendering issues
tried this get locale whenever you intialize LocaleProvider class:-
import 'package:flutter/material.dart';
import 'package:myapp/l10n/l10n.dart';
import 'package:shared_preferences/shared_preferences.dart';
class LocaleProvider extends ChangeNotifier {
Locale? locale;
LocaleProvider({this.locale});
Locale? get locale => _locale;
void setLocale(Locale locale) {
if (!L10n.all.contains(locale)) return;
_locale = locale;
notifyListeners();
//setLocaleSettings(locale);
}
void clearLocale() {
_locale = null;
notifyListeners();
}
void changeLocaleSettings(Locale newLocale) async {
if(newLocale == Locale('en')) {
_locale = Locale('en');
} else if(newLocale==Locale('uk')){
_locale = Locale('uk');
} else if(newLocale==Locale('ru')){
_locale = Locale('ru');
}
SharedPreferences prefs = await SharedPreferences.getInstance();
await prefs.setString("code", _locale?.countryCode??"en");
notifyListeners();
}
Future getLocaleFromSettings() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String code = prefs.getString("code")??"en";
Locale newLocale = Locale(code);
if(newLocale == Locale('en')) {
_locale = Locale('en');
} else if(newLocale==Locale('uk')){
_locale = Locale('uk');
} else if(newLocale==Locale('ru')){
_locale = Locale('ru');
}
}
}
use this in main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences _sharedPreferences = await SharedPreferences.getInstance();
string savedLangugae = get from sharepreference;
runApp(MultiProvider(providers: [
ChangeNotifierProvider(create: (_) => LocaleProvider(locale:Locale(savedLanguage))),
], child: const MyApp()));
}
Hope it will work.
I am trying to modify the following code that uses stateful widgets and provider package to use GetX package and stateless widgets instead. In a part of code it specifies if the user is authenticated or not to show the home or auth screen. This is the auth_controller.dart code:
class Auth with ChangeNotifier {
String? _token;
DateTime? _expiryDate;
String? _userId;
Timer? _authTimer;
bool get isAuth {
return token != null;
}
String? get token {
if (_expiryDate != null &&
_expiryDate!.isAfter(DateTime.now()) &&
_token != null) {
return _token;
}
return null;
}
String? get userId {
return _userId;
}
Future<void> _authenticate(
String email, String password, String urlSegment) async {
final host = Platform.isAndroid ? '10.0.2.2' : '127.0.0.1';
final url = Uri.parse('http://$host:8080/api/$urlSegment');
// final url = Uri.parse('http://10.0.2.2:8000/api/$urlSegment');
// final url = Uri.parse('http://127.0.0.1:8000/api/$urlSegment');
try {
final http.Response response = await http.post(
url,
headers: {"Content-Type": "application/json"},
body: json.encode(
{
'email': email,
'password': password,
//'returnSecureToken': true,
},
),
);
final responseData = json.decode(response.body);
if (responseData['error'] != null) {
throw HttpException(responseData['error']['message']);
} else {
_token = responseData['idToken'];
_userId = responseData['id'];
_expiryDate = DateTime.now().add(
Duration(
seconds: responseData['expiresIn'],
),
);
}
_autoLogout();
notifyListeners();
final prefs = await SharedPreferences.getInstance();
final userData = json.encode(
{
'token': _token,
'userId': _userId,
'expiryDate': _expiryDate!.toIso8601String(),
},
);
prefs.setString('userData', userData);
} catch (error) {
throw error;
}
}
Future<void> signup(String email, String password) async {
return _authenticate(email, password, 'register');
}
Future<void> login(String email, String password) async {
return _authenticate(email, password, 'login');
}
Future<bool> tryAutoLogin() async {
final prefs = await SharedPreferences.getInstance();
if (!prefs.containsKey('userData')) {
return false;
}
final Map<String, Object> extractedUserData = Map<String, Object>.from(
json.decode(prefs.getString('userData') as String));
final expiryDate =
DateTime.parse(extractedUserData['expiryDate'] as String);
if (expiryDate.isBefore(DateTime.now())) {
return false;
}
_token = extractedUserData['token'] as String;
_userId = extractedUserData['userId'] as String;
_expiryDate = expiryDate;
notifyListeners();
_autoLogout();
return true;
}
Future<void> logout() async {
_token = null;
_userId = null;
_expiryDate = null;
if (_authTimer != null) {
_authTimer!.cancel();
_authTimer = null;
}
notifyListeners();
final prefs = await SharedPreferences.getInstance();
// prefs.remove('userData');
prefs.clear();
}
void _autoLogout() {
if (_authTimer != null) {
_authTimer!.cancel();
}
final timeToExpiry = _expiryDate!.difference(DateTime.now()).inSeconds;
_authTimer = Timer(Duration(seconds: timeToExpiry), logout);
}
}
and this is main.dart:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider.value(
value: Auth(),
),
],
child: Consumer<Auth>(
builder: (ctx, auth, _) => MaterialApp(
title: 'MyShop',
theme: ThemeData(
primarySwatch: Colors.purple,
accentColor: Colors.deepOrange,
fontFamily: 'Lato',
),
home: auth.isAuth
? MainScreen()
: FutureBuilder(
future: auth.tryAutoLogin(),
builder: (ctx, authResultSnapshot) =>
authResultSnapshot.connectionState ==
ConnectionState.waiting
? SplashScreen()
: AuthScreen(),
),
routes: {
MainScreen.routeName: (ctx) => const MainScreen(),
UserAccountScreen.routeName: (ctx) => const UserAccountScreen(),
},
),
),
);
}
I tried to change the class to extend GetXController, also make some variables as observable by adding .obs at the end of them and listening to their changes by wrapping the listener part inside the Obx. But I don't know what should I do with isAuth variable? It seems my new code after modification can not update the isAuth state and it is always `false and this keeps the authentication page always up and no way to go into the application for users.
EDIT: This is the main.dart after modification:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return GetMaterialApp(
initialRoute: AuthController.instance.isAuth
? homeScreenRoute
: authenticationScreenRoute,
unknownRoute: GetPage(
name: '/not-found',
page: () => PageNotFound(),
transition: Transition.fadeIn),
getPages: [
GetPage(
name: rootRoute,
page: () {
return SiteLayout();
}),
GetPage(
name: authenticationScreenRoute,
page: () => const AuthenticationScreen()),
GetPage(name: homeScreenRoute, page: () => HomeScreen()),
],
debugShowCheckedModeBanner: false,
title: 'BasicCode',
theme: ThemeData(
scaffoldBackgroundColor: light,
textTheme: GoogleFonts.mulishTextTheme(Theme.of(context).textTheme)
.apply(bodyColor: Colors.black),
pageTransitionsTheme: const PageTransitionsTheme(builders: {
TargetPlatform.iOS: FadeUpwardsPageTransitionsBuilder(),
TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
}),
primarySwatch: Colors.blue,
),
// home: AuthenticationPage(),
);
}
}
You can wrap your stateless widget with GetBuilder(), like this:
GetBuilder<YourController>(
id: 'id_name',
builder: (controller) {
if (controller.isAuth) {
return OneWidget();
} else {
return SecondWidget();
}
}
Do you need use update(['id_name']) after change value of isAuth, this produce a rebuild of GetBuilder.
I want to store value of share preference in to class variable but it doesn't working at all, the value doesn't store to variable.
here is my code, basically i want to store to variable _uid but when i accessing it inside my UI it printing ""..
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class User with ChangeNotifier {
FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
Firestore _firestore = Firestore.instance;
bool _loggedIn = false;
bool get loggedIn => _loggedIn;
String _uid = "";
String get uid => _uid;
User() {
getPrefState().then((val) {
// do some operation
_uid = val.toString() ?? "test";
});
//init();
}
Future init() async {
//var data;
//_uid = getPrefState();
/*SharedPreferences.getInstance().then((value) => {
_uid = value.getString("uid") ?? "d",
data = "dsdasd",
});*/
/*try {
SharedPreferences prefs = await SharedPreferences.getInstance();
_uid = data;
} catch (err) {
//pass.
}*/
//var uid = prefs.getString("uid") ?? "d";
/*if (uid != null) {
_loggedIn = true;
}*/
//_uid = "dsd";
//notifyListeners();
}
Future<String> getPrefState() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
//Return String
String stringValue = prefs.getString('uid') ?? "test";
return stringValue;
}
Future<void> saveId(uid) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString("uid", uid);
}
Future<void> saveUserInDocument(String uid, String name, String sap) {
_firestore.collection("users").document(uid).setData({
"name": name,
"sap": sap,
'role': "student",
});
}
Future<FirebaseUser> getCurrentUser() async {
return await _firebaseAuth.currentUser();
}
// user signup.
Future<void> signup(
String email, String password, String name, String sap) async {
FirebaseUser user = (await _firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password))
.user;
if (user != null) {
saveUserInDocument(user.uid, name, sap);
saveId(user.uid);
_loggedIn = true;
notifyListeners();
}
}
/// user login
Future<void> login(String email, String password) async {
FirebaseUser user = (await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password))
.user;
//if (user != null) {
saveId(user.uid);
_loggedIn = true;
notifyListeners();
//}
}
/// User logout
Future<void> logout() async {
_firebaseAuth.signOut();
saveId(null);
_loggedIn = false;
notifyListeners();
}
/// reset user password
Future<void> resetPassword(String email) async {
await _firebaseAuth.sendPasswordResetEmail(email: email);
}
}
Here is my UI class where i want to use it
user.uid
import "package:flutter/material.dart";
import 'package:riphahwebresources/data/User.dart';
import 'package:riphahwebresources/pages/auth/login_ui.dart';
import 'package:shared_preferences/shared_preferences.dart';
class WebResourceAppDrawer extends StatefulWidget {
#override
_WebResourceAppDrawerState createState() => _WebResourceAppDrawerState();
}
class _WebResourceAppDrawerState extends State<WebResourceAppDrawer> {
User user = User();
#override
Widget build(BuildContext context) {
List<Widget> children = [];
children.add(
ListTile(
leading: Icon(Icons.home),
title: Text("Home"),
),
);
if (user.loggedIn) {
children.add(ListTile(
leading: Icon(Icons.people),
title: Text("Profile"),
onTap: () => {
Navigator.push(
context, MaterialPageRoute(builder: (context) => LoginUi()))
},
));
children.add(ListTile(
leading: Icon(Icons.people),
title: Text("Logout"),
onTap: () => {
Navigator.push(
context, MaterialPageRoute(builder: (context) => LoginUi()))
},
));
} else {
children.add(ListTile(
leading: Icon(Icons.people),
title: Text(user.uid),
onTap: () => {
Navigator.push(
context, MaterialPageRoute(builder: (context) => LoginUi()))
},
));
}
return Drawer(
child: ListView(
padding: const EdgeInsets.all(8),
children: <Widget>[
DrawerHeader(
child: Text("Menu"),
),
...children,
],
),
);
}
}
You can see from method init i try different things but idk nothing works for me.
Thanks you so much.
When using ChangeNotifier, you need to call notifyListeners to propagate the change to your UI class:
notifyListeners(). Call this method any time the model changes in a way that might change your app’s UI.
Flutter Docs on State Management
As a reminder, you need the following 3 things to get State Management working:
Setup a class that extends ChangeNotifier (which you have done, but just replace the with with extends)
Add a ChangeNotifierProvider above the widget where you require the value (i.e. above your WebResourceAppDrawer UI widget)
Now access User by wrapping your UI widget with Consumer<User>
Here's what a complete, minimal example would look like:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: Center(
child:
ChangeNotifierProvider(create: (_) => User(), child: UI()))),
// 'UI' can now access the newly created User() since it's a
// child of ChangeNotifierProvider
);
}
}
class UI extends StatefulWidget {
#override
_UIState createState() => _UIState();
}
class _UIState extends State<UI> {
#override
Widget build(BuildContext context) {
return Container(
child: Consumer<User>(
builder: (context, user, child) => Text("User ${user.uid}")),
// This is how user can be accessed within UI
);
}
}
class User extends ChangeNotifier {
String _uid = "(empty)";
String get uid => _uid;
User() {
getPrefState().then((val) {
_uid = val;
notifyListeners(); // this call triggers a rebuild of UI
});
}
getPrefState() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString('uid');
}
}
My app can not load the login UI it is just stuck on loading the CircularProgressIndicator():
here is my code provider code When i run the application it shows no error at all but then the app does not load the login UI:
main.dart
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider.value(value: UserProvider.initialize())
],
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'AfriMarKet',
theme: ThemeData(
primaryColor: Colors.white
),
home: ScreensController());
}
}
class ScreensController extends StatelessWidget {
#override
Widget build(BuildContext context) {
final user = Provider.of<UserProvider>(context);
switch (user.status) {
case Status.Uninitialized:
return SplashScreen();
case Status.Unauthenticated:
case Status.Authenticating:
return LoginPage();
case Status.Authenticated:
return HomePage();
default:
return LoginPage();
}
}
}
provider.dart
enum Status { Uninitialized, Authenticated, Authenticating, Unauthenticated }
class UserProvider extends ChangeNotifier{
FirebaseAuth _auth;
FirebaseUser _user;
Status _status = Status.Uninitialized;
Status get status => _status;
FirebaseUser get user => _user;
Firestore _firestore = Firestore.instance;
UserServices _userServices = UserServices();
UserProvider.initialize(): _auth = FirebaseAuth.instance{
_auth.onAuthStateChanged.listen(_onStateChanged);
}
Future<bool> signIn(String email, String password)async{
try{
_status = Status.Authenticating;
notifyListeners();
await _auth.signInWithEmailAndPassword(email: email, password: password);
return true;
}catch(e){
_status = Status.Unauthenticated;
notifyListeners();
print(e.toString());
return false;
}
}
Future<bool> signUp(String name,String email, String password)async{
try{
_status = Status.Authenticating;
notifyListeners();
await _auth.createUserWithEmailAndPassword(email: email, password: password).then((user){
_firestore.collection('users').document(user.user.uid).setData({
'name':name,
'email':email,
'uid':user.user.uid
});
});
return true;
}catch(e){
_status = Status.Unauthenticated;
notifyListeners();
print(e.toString());
return false;
}
}
Future signOut()async{
_auth.signOut();
_status = Status.Unauthenticated;
notifyListeners();
return Future.delayed(Duration.zero);
}
Future<void> _onStateChanged(FirebaseUser user) async{
if(user == null){
_status = Status.Unauthenticated;
}else{
_user = user;
_status = Status.Authenticated;
}
notifyListeners();
}
}
Thank you all for the help I finally figured it out, the issue was that I added this part of the code
Visibility(
child: Center(
child: Container(
alignment: Alignment.center,
color: Colors.white.withOpacity(0.9),
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.red),
),
),
),
)
as the last widget inside my Scaffold and it caused all my Nightmares of my loginPage
please I tried to set SystemChrome.setSystemUiOverlayStyle() based on a condition that is bool value stored in phone using shared_preferences. Even if dark mode is true or not, SystemChrome.setSystemUiOverlayStyle did not work or changed on the condition when app launched. Sorry my bad English grammar. Below is my code:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:kjv_bible/screens/book_chapters.dart';
import 'package:kjv_bible/screens/home_page.dart';
import 'package:kjv_bible/utils/color_helper.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'providers/setting_provider.dart';
import 'package:provider/provider.dart';
import 'models/theme_preferences.dart';
void main() => runApp(Bible());
class Bible extends StatefulWidget {
#override
_BibleState createState() => _BibleState();
}
class _BibleState extends State<Bible> {
SharedPreferences _prefs;
bool _isDark;
#override
void initState() {
setTheme();
super.initState();
}
void setTheme() async {
_isDark = false;
if (_prefs == null) _prefs = await SharedPreferences.getInstance();
if (_prefs.containsKey('theme')) {
_isDark = _prefs.getBool('theme') == true ? true : false;
} else {
_isDark = false;
}
if (_isDark) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
systemNavigationBarColor: color("#232D36"),
statusBarColor: color("#101D25"),
));
} else {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
systemNavigationBarColor: Colors.white,
statusBarColor: color("#22A2EE"),
));
}
}
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider.value(value: SettingProvider()),
],
child: Consumer<SettingProvider>(builder: (ctx, status, _) {
return MaterialApp(
theme: status.darkTheme ? darkTheme : lightTheme,
title: "Bible",
debugShowCheckedModeBanner: false,
home: HomePage(),
routes: {
BookChapters.routeName: (ctx) => BookChapters(),
},
);
}),
);
}
}
Try this:
void main() async{
WidgetsFlutterBinding.ensureInitialized();
await setTheme();
runApp(Bible());
}
Just a side note, try using Dart features in your code
if (_prefs == null) _prefs = await SharedPreferences.getInstance();
_prefs ??= await SharedPreferences.getInstance();
.
if (_prefs.containsKey('theme')) {
_isDark = _prefs.getBool('theme') == true ? true : false;
} else {
_isDark = false;
}
_isDark = _prefs.containKey('theme') ? _prefs.getBool('theme') : false;