Flutter登录按钮点击后状态未触发,页面不跳转问题求助
问题:登录成功后页面不自动跳转,需手动刷新
所有功能正常,但点击登录按钮后,用户已成功登录,但页面不会自动切换到登录后的界面,必须手动刷新才会更新状态,使用setState也无法解决。
Root页面代码
import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:login/main.dart'; import 'package:login/services/auth_service.dart'; class Root extends StatefulWidget { const Root({Key? key}) : super(key: key); @override State<Root> createState() => _RootState(); } enum AuthState { signedIn, signedOut } class _RootState extends State<Root> { AuthState _authState = AuthState.signedOut; AuthService auth = AuthService(); String authuser = "ghnfgjy"; void signOut() async { await auth.signOut(); setState(() { _authState = AuthState.signedOut; }); } void signIn() async { setState(() { _authState = AuthState.signedIn; }); } @override void initState() { super.initState(); auth.currentUser().then((user) { print("check check $user "); setState(() { _authState = user == null ? AuthState.signedOut : AuthState.signedIn; }); }); } @override Widget build(BuildContext context) { if (_authState == AuthState.signedOut) { return Login(); } else { return Scaffold( body: Center( child: Column( children: [ SizedBox( height: 69, ), Text("Helllloooooooo $authuser"), SizedBox( height: 45, ), FlatButton( onPressed: () { signOut(); }, child: Text("Sign out")) ], ), )); } } }
Login页面代码
import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:login/main.dart'; import 'package:login/services/auth_service.dart'; import 'package:login/share/constant.dart'; class Login extends StatefulWidget { const Login({Key? key}) : super(key: key); @override _LoginState createState() => _LoginState(); } enum FormType { login, register, } class _LoginState extends State<Login> { dynamic _email; dynamic _password; final formkey = GlobalKey<FormState>(); FormType _formType = FormType.login; dynamic result; AuthService auth = AuthService(); bool validateandsave() { final form = formkey.currentState; if (form!.validate()) { form.save(); print('form is valid'); print('$_email $_password'); return true; } else { print('form is not valid'); return false; } } Future validateandsumit() async { if (validateandsave()) { if (_formType == FormType.register) { auth.register(_email, _password); setState(() { _formType = FormType.login; }); } else { auth.signIn(_email, _password); } } } void moveToRegister() { formkey.currentState!.reset(); setState(() { _formType = FormType.register; }); } void moveToLogin() { formkey.currentState!.reset(); setState(() { _formType = FormType.login; }); } @override Widget build(BuildContext context) { return Scaffold( body: Container( decoration: BoxDecoration( gradient: const LinearGradient( begin: Alignment.topRight, end: Alignment.bottomLeft, colors: [ Colors.blueAccent, Colors.purple, ], ), ), padding: EdgeInsets.all(16), child: Form( key: formkey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisAlignment: MainAxisAlignment.center, children: openText() + inputFields() + buttons(), ), ), ), ); } List<Widget> openText() { if (_formType == FormType.register) { return [ Text( 'Please Register to continue', style: TextStyle( fontSize: 35, color: Colors.white, fontWeight: FontWeight.bold), textAlign: TextAlign.center, ), SizedBox( height: 40, ), ]; } else { return [ Text('Please Login to continue', style: TextStyle( fontSize: 35, color: Colors.white, fontWeight: FontWeight.bold), textAlign: TextAlign.center), SizedBox( height: 40, ), ]; } } List<Widget> inputFields() { return [ TextFormField( decoration: inputDecoration.copyWith( labelText: 'Email Address', ), style: TextStyle(color: Colors.black), validator: (val) => val!.isEmpty ? 'Enter the email address' : null, onSaved: (val) => _email = val), SizedBox( height: 20, ), TextFormField( obscureText: true, decoration: inputDecoration.copyWith( labelText: 'Password', ), style: TextStyle(color: Colors.black), validator: (val) => val!.isEmpty ? 'Enter the password' : null, onSaved: (val) => _password = val), SizedBox( height: 60, ), ]; } List<Widget> buttons() { if (_formType == FormType.register) { return [ FlatButton( padding: EdgeInsets.symmetric(vertical: 10, horizontal: 60), onPressed: validateandsumit, child: Text( 'Register', style: TextStyle(fontSize: 20, color: Colors.white), ), color: Colors.pinkAccent, ), SizedBox( height: 20, ), FlatButton( padding: EdgeInsets.symmetric(vertical: 10, horizontal: 60), onPressed: moveToLogin, child: Text( 'Have an account? Login', style: TextStyle(fontSize: 20, color: Colors.white), ), color: Colors.pinkAccent, ), ]; } else { return [ FlatButton( padding: EdgeInsets.symmetric(vertical: 10, horizontal: 60), onPressed: validateandsumit, child: Text( 'Login', style: TextStyle(fontSize: 20, color: Colors.white), ), color: Colors.pinkAccent, ), SizedBox( height: 20, ), FlatButton( padding: EdgeInsets.symmetric(vertical: 10, horizontal: 60), onPressed: moveToRegister, child: Text( 'Register', style: TextStyle(fontSize: 20, color: Colors.white), ), color: Colors.pinkAccent, ), ]; } } }
AuthService代码
import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; class AuthService { FirebaseAuth _auth = FirebaseAuth.instance; //Stream <User>? get authStateChanges => _auth.authStateChanges(); Stream<User?> get authStateChanges => _auth.authStateChanges(); CollectionReference users = FirebaseFirestore.instance.collection('users'); late User user; //register in with email and password Future register(email, password) async { try { UserCredential userCredential = await _auth .createUserWithEmailAndPassword(email: email, password: password); user = userCredential.user!; print('Registered ${user.uid}'); var userdata = { 'email': email, 'password': password, 'role': 'user', }; users.doc(user.uid).get().then((doc) { if (doc.exists) { doc.reference.update(userdata); } else { users.doc(user.uid).set(userdata); } }); } catch (e) { print(e); } } //sign in with email and password Future signIn(email, password) async { try { UserCredential userCredential = await _auth.signInWithEmailAndPassword( email: email, password: password); user = userCredential.user!; print('logged in ${user.uid}'); var userdata = { 'email': email, 'password': password, 'role': 'user', }; users.doc(user.uid).get().then((doc) { if (doc.exists) { doc.reference.update(userdata); } else { users.doc(user.uid).set(userdata); } }); } catch (e) { print(e); } } Future currentUser() async { try { User user = await _auth.currentUser!; return user.uid; } catch (e) { print(e); } } //sign out Future signOut() async { try { await _auth.signOut(); } catch (e) { print(e); } } }
解决方案
问题根源在于Root页面只在initState时检查一次用户登录状态,登录操作完成后没有触发状态更新。正确的做法是监听Firebase Auth的状态流,实时更新UI。
修改Root页面代码:
- 移除
initState中的单次检查,改为监听auth.authStateChanges流 - 订阅流并在状态变化时更新
_authState
修改后的_RootState代码:
class _RootState extends State<Root> { AuthState _authState = AuthState.signedOut; AuthService auth = AuthService(); String authuser = "ghnfgjy"; StreamSubscription? _authSubscription; void signOut() async { await auth.signOut(); } @override void initState() { super.initState(); // 监听Auth状态变化 _authSubscription = auth.authStateChanges.listen((User? user) { setState(() { _authState = user == null ? AuthState.signedOut : AuthState.signedIn; if (user != null) { authuser = user.uid; // 更新用户ID } }); }); } @override void dispose() { _authSubscription?.cancel(); // 页面销毁时取消订阅,避免内存泄漏 super.dispose(); } @override Widget build(BuildContext context) { if (_authState == AuthState.signedOut) { return Login(); } else { return Scaffold( body: Center( child: Column( children: [ SizedBox( height: 69, ), Text("Helllloooooooo $authuser"), SizedBox( height: 45, ), FlatButton( onPressed: signOut, child: Text("Sign out")) ], ), )); } } }
额外优化点:
signOut方法中无需手动调用setState,因为监听流会自动捕获登出状态- 更新
authuser为当前登录用户的UID,避免固定字符串 - 添加流订阅的取消操作,防止内存泄漏
这样修改后,登录/登出操作完成后,Auth状态流会自动触发setState,页面会实时刷新,无需手动刷新。
内容的提问来源于stack exchange,提问作者Divya
相关产品推荐
相关产品推荐

