admin管理员组文章数量:1417685
I'm using Firebase Authentication in my Flutter app to detect user authentication state changes and navigate accordingly. However, the navigation inside initState
does not work.
./main.dart:
import 'package:app/authentication/email_auth.dart';
import 'package:app/authentication/landing.dart';
import 'package:app/authentication/signup.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'authentication/login.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
User? _user;
@override
void initState() {
super.initState();
FirebaseAuth.instance.authStateChanges().listen((user) {
print("User state changed: ${user?.uid}");
FocusManager.instance.primaryFocus?.unfocus();
setState(() {
_user = user;
});
if (user != null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => HomeScreen()),
(route) => false,
);
});
}
});
}
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarIconBrightness: ThemeMode.system == ThemeMode.light
? Brightness.dark
: Brightness.light));
return MaterialApp(
// app data
title: 'MyApp',
// app navigation
routes: {
Login.routeName: (context) => const Login(),
Signup.routeName: (context) => const Signup(),
EmailAuth.routeName: (context) => const EmailAuth(),
Landing.routeName: (context) => const Landing(),
HomeScreen.routeName: (context) => HomeScreen(),
},
home: Landing(),
themeMode: ThemeMode.dark,
theme: ThemeData(scaffoldBackgroundColor: Color(0xff222531)),
darkTheme: ThemeData(
scaffoldBackgroundColor: Color(0xff222531),
bottomAppBarTheme: BottomAppBarTheme(color: Colors.red),
useMaterial3: true,
textTheme: TextTheme(
labelMedium: GoogleFonts.inter(
color: Colors.white, fontWeight: FontWeight.bold, fontSize: 20),
labelSmall: GoogleFonts.inter(
color: Colors.white, fontWeight: FontWeight.bold, fontSize: 13),
bodyLarge: GoogleFonts.inter(
color: Colors.white, fontWeight: FontWeight.w500, fontSize: 24),
headlineSmall: GoogleFonts.inter(
color: Colors.white, fontWeight: FontWeight.w400, fontSize: 22),
displayMedium: GoogleFonts.montserrat(
color: Colors.white, fontWeight: FontWeight.bold, fontSize: 40),
headlineLarge: GoogleFonts.inter(
color: Colors.white, fontWeight: FontWeight.w400)),
),
);
}
}
class HomeScreen extends StatelessWidget {
HomeScreen({
super.key,
});
static const routeName = "/home";
final user = FirebaseAuth.instance.currentUser;
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTap: () async {
print("pressed");
await FirebaseAuth.instance.signOut();
},
child: Center(
child: Text(
user?.email ?? "hello",
style: Theme.of(context).textTheme.headlineLarge,
),
),
),
);
}
}
Issue:
- The authentication state change is detected (confirmed by
print()
logs). - However,
Navigator.pushAndRemoveUntil
does not work, and the screen does not change.
How can I fix this issue and ensure the navigation happens when the user logs in?
Things I Have Tried:
- Wrapping
Navigator.pushAndRemoveUntil
insideWidgetsBinding.instance.addPostFrameCallback
- Checking if mounted before calling
Navigator
- Adding a small delay with
Future.delayed(Duration(milliseconds: 100), () {...})
- Moving navigation logic to
build()
instead ofinitState
- Ensuring
MaterialPageRoute
is correctly defined - None of these solutions have worked.
I was expecting the sign-in to go ahead and the user be navigated to the homePage() page. But in reality the sign in is successful while the navigation is not!
I'm using Firebase Authentication in my Flutter app to detect user authentication state changes and navigate accordingly. However, the navigation inside initState
does not work.
./main.dart:
import 'package:app/authentication/email_auth.dart';
import 'package:app/authentication/landing.dart';
import 'package:app/authentication/signup.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'authentication/login.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'firebase_options.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
User? _user;
@override
void initState() {
super.initState();
FirebaseAuth.instance.authStateChanges().listen((user) {
print("User state changed: ${user?.uid}");
FocusManager.instance.primaryFocus?.unfocus();
setState(() {
_user = user;
});
if (user != null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => HomeScreen()),
(route) => false,
);
});
}
});
}
@override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarIconBrightness: ThemeMode.system == ThemeMode.light
? Brightness.dark
: Brightness.light));
return MaterialApp(
// app data
title: 'MyApp',
// app navigation
routes: {
Login.routeName: (context) => const Login(),
Signup.routeName: (context) => const Signup(),
EmailAuth.routeName: (context) => const EmailAuth(),
Landing.routeName: (context) => const Landing(),
HomeScreen.routeName: (context) => HomeScreen(),
},
home: Landing(),
themeMode: ThemeMode.dark,
theme: ThemeData(scaffoldBackgroundColor: Color(0xff222531)),
darkTheme: ThemeData(
scaffoldBackgroundColor: Color(0xff222531),
bottomAppBarTheme: BottomAppBarTheme(color: Colors.red),
useMaterial3: true,
textTheme: TextTheme(
labelMedium: GoogleFonts.inter(
color: Colors.white, fontWeight: FontWeight.bold, fontSize: 20),
labelSmall: GoogleFonts.inter(
color: Colors.white, fontWeight: FontWeight.bold, fontSize: 13),
bodyLarge: GoogleFonts.inter(
color: Colors.white, fontWeight: FontWeight.w500, fontSize: 24),
headlineSmall: GoogleFonts.inter(
color: Colors.white, fontWeight: FontWeight.w400, fontSize: 22),
displayMedium: GoogleFonts.montserrat(
color: Colors.white, fontWeight: FontWeight.bold, fontSize: 40),
headlineLarge: GoogleFonts.inter(
color: Colors.white, fontWeight: FontWeight.w400)),
),
);
}
}
class HomeScreen extends StatelessWidget {
HomeScreen({
super.key,
});
static const routeName = "/home";
final user = FirebaseAuth.instance.currentUser;
@override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTap: () async {
print("pressed");
await FirebaseAuth.instance.signOut();
},
child: Center(
child: Text(
user?.email ?? "hello",
style: Theme.of(context).textTheme.headlineLarge,
),
),
),
);
}
}
Issue:
- The authentication state change is detected (confirmed by
print()
logs). - However,
Navigator.pushAndRemoveUntil
does not work, and the screen does not change.
How can I fix this issue and ensure the navigation happens when the user logs in?
Things I Have Tried:
- Wrapping
Navigator.pushAndRemoveUntil
insideWidgetsBinding.instance.addPostFrameCallback
- Checking if mounted before calling
Navigator
- Adding a small delay with
Future.delayed(Duration(milliseconds: 100), () {...})
- Moving navigation logic to
build()
instead ofinitState
- Ensuring
MaterialPageRoute
is correctly defined - None of these solutions have worked.
I was expecting the sign-in to go ahead and the user be navigated to the homePage() page. But in reality the sign in is successful while the navigation is not!
Share Improve this question edited Jan 31 at 11:03 squarewatermeln asked Jan 31 at 10:12 squarewatermelnsquarewatermeln 33 bronze badges 1- Did/could you try stackoverflow/questions/66532753/… and or stackoverflow/q/51965326/209103? – Frank van Puffelen Commented Jan 31 at 16:19
1 Answer
Reset to default 0Ok so here's how i fixed it:
i moved to contextless navigation, so i defined a GlobalKey<NavigatorState>
globally in main.dart:
./main.dart:
// global navigation
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
then inside initState()
(main.dart
):
FirebaseAuth.instance.authStateChanges().listen((user) {
FocusManager.instance.primaryFocus?.unfocus();
setState(() {
_user = user;
});
if (user != null) {
navigatorKey.currentState?.pushNamed("/home");
}
});
and in MaterialApp()
(main.dart
) you have to add this line:
navigatorKey: navigatorKey,
however i am yet to investigate the potential drawbacks with this approach (when i find them i will list them down below)
本文标签: firebaseFlutter FirebaseAuth authStateChanges Not Navigating in initStateStack Overflow
版权声明:本文标题:firebase - Flutter FirebaseAuth authStateChanges Not Navigating in initState - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745269742a2650815.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论