Flutter项目启动页因Firebase登录逻辑冻结问题求助
Flutter启动页冻结问题:仅显示UI无法完成跳转
我正在开发一个Flutter项目,启动页逻辑如下:
- 检查SharedPreference中是否存在登录凭证
- 若存在,尝试通过Firebase自动登录:
- 登录无异常则跳转HomeScreen
- 出现错误则重置凭证并跳转LoginOrSignUp页
- 若不存在凭证则直接跳转LoginOrSignUp页
目前启动页出现冻结问题,仅能显示UI,无法完成后续跳转逻辑。
getDataAndCheck函数代码
void getDataAndCheck() async { bool emailPresent = await sharedPreference().checkValuePresent('email'); bool passwordPresent = await sharedPreference().checkValuePresent('password'); email = (await sharedPreference().getCred('email')) ?? ''; password = (await sharedPreference().getCred('password')) ?? ''; Timer(const Duration(seconds: 3), () { print('Email: $email\nPassword: $password'); if (emailPresent == true && passwordPresent == true) { print('inside if'); firebaseAuth .signInWithEmailAndPassword(email: email, password: password) .catchError((errMsg) { print('inside catch error'); if (errMsg.code == null) { print('When Null'); Navigator.pushAndRemoveUntil( context, PageRouteBuilder( transitionDuration: const Duration(seconds: 1), transitionsBuilder: (context, animation, animationTime, child) { animation = CurvedAnimation( parent: animation, curve: Curves.fastLinearToSlowEaseIn); return ScaleTransition( scale: animation, alignment: Alignment.center, child: child, ); }, pageBuilder: (context, animation, animationTime) { return const HomeScreen(); }, ), (route) => false, ); } else { print('When Not Null'); sharedPreference().reset(); Navigator.pushReplacement( context, PageRouteBuilder( transitionDuration: const Duration(seconds: 1), transitionsBuilder: (context, animation, animationTime, child) { animation = CurvedAnimation( parent: animation, curve: Curves.fastLinearToSlowEaseIn); return ScaleTransition( scale: animation, alignment: Alignment.center, child: child, ); }, pageBuilder: (context, animation, animationTime) { return const LoginOrSignUp(); }, ), ); } }); } else { print('When email and password in not present'); sharedPreference().reset(); Navigator.pushReplacement( context, PageRouteBuilder( transitionDuration: const Duration(seconds: 1), transitionsBuilder: (context, animation, animationTime, child) { animation = CurvedAnimation( parent: animation, curve: Curves.fastLinearToSlowEaseIn); return ScaleTransition( scale: animation, alignment: Alignment.center, child: child, ); }, pageBuilder: (context, animation, animationTime) { return const LoginOrSignUp(); }, ), ); } }); }
initState调用代码
@override void initState() { super.initState(); getDataAndCheck(); }
运行时错误日志
Performing hot restart... Syncing files to device sdk gphone64 x86 64... Restarted application in 3,201ms. W/DynamiteModule(15758): Local module descriptor class for com.google.android.gms.providerinstaller.dynamite not found. I/DynamiteModule(15758): Considering local module com.google.android.gms.providerinstaller.dynamite:0 and remote module com.google.android.gms.providerinstaller.dynamite:0 W/ProviderInstaller(15758): Failed to load providerinstaller module: No acceptable module com.google.android.gms.providerinstaller.dynamite found. Local version is 0 and remote version is 0. W/ConnectivityManager.CallbackHandler(15758): callback not found for CALLBACK_AVAILABLE message D/EGL_emulation(15758): app_time_stats: avg=58800.26ms min=766.16ms max=116834.36ms count=2 D/EGL_emulation(15758): app_time_stats: avg=1744.28ms min=1744.28ms max=1744.28ms count=1 I/flutter (15758): Email: abc123@gmail.com I/flutter (15758): Password: 123456 I/flutter (15758): inside if W/System (15758): Ignoring header X-Firebase-Locale because its value was null. W/System (15758): Ignoring header X-Firebase-Locale because its value was null. D/FirebaseAuth(15758): Notifying id token listeners about user ( NcSwfsdw7fc6ZFXH0ylSRMNonW63 ). D/EGL_emulation(15758): app_time_stats: avg=3078.58ms min=3078.58ms max=3078.58ms count=1
问题分析与解决方案
从日志能看到Firebase已经成功登录(Notifying id token listeners about user),但跳转逻辑没执行,核心问题出在以下几点:
catchError只捕获异常,未处理登录成功的情况signInWithEmailAndPassword成功时不会进入catchError分支,导致登录成功后没有触发跳转HomeScreen的逻辑,启动页一直停滞。Timer完全冗余,可能引发context状态问题
已经用async/await处理了SharedPreference的异步操作,额外添加Timer不仅没必要,还可能导致context失效或逻辑延迟。SharedPreference实例重复创建
每次调用sharedPreference()都会生成新实例,建议复用同一个实例以优化性能。
修改后的代码
void getDataAndCheck() async { final prefs = sharedPreference(); // 复用同一个SharedPreference实例 bool emailPresent = await prefs.checkValuePresent('email'); bool passwordPresent = await prefs.checkValuePresent('password'); email = (await prefs.getCred('email')) ?? ''; password = (await prefs.getCred('password')) ?? ''; print('Email: $email\nPassword: $password'); if (emailPresent && passwordPresent) { print('inside if'); try { // 用try-catch覆盖登录成功和失败两种场景 await firebaseAuth.signInWithEmailAndPassword( email: email, password: password, ); // 登录成功跳转主页 print('Login success'); Navigator.pushAndRemoveUntil( context, PageRouteBuilder( transitionDuration: const Duration(seconds: 1), transitionsBuilder: (context, animation, animationTime, child) { animation = CurvedAnimation( parent: animation, curve: Curves.fastLinearToSlowEaseIn, ); return ScaleTransition( scale: animation, alignment: Alignment.center, child: child, ); }, pageBuilder: (context, animation, animationTime) { return const HomeScreen(); }, ), (route) => false, ); } catch (errMsg) { print('inside catch error: ${errMsg.toString()}'); // 登录失败,重置凭证并跳转登录页 await prefs.reset(); Navigator.pushReplacement( context, PageRouteBuilder( transitionDuration: const Duration(seconds: 1), transitionsBuilder: (context, animation, animationTime, child) { animation = CurvedAnimation( parent: animation, curve: Curves.fastLinearToSlowEaseIn, ); return ScaleTransition( scale: animation, alignment: Alignment.center, child: child, ); }, pageBuilder: (context, animation, animationTime) { return const LoginOrSignUp(); }, ), ); } } else { print('When email and password in not present'); await prefs.reset(); Navigator.pushReplacement( context, PageRouteBuilder( transitionDuration: const Duration(seconds: 1), transitionsBuilder: (context, animation, animationTime, child) { animation = CurvedAnimation( parent: animation, curve: Curves.fastLinearToSlowEaseIn, ); return ScaleTransition( scale: animation, alignment: Alignment.center, child: child, ); }, pageBuilder: (context, animation, animationTime) { return const LoginOrSignUp(); }, ), ); } }
额外优化建议
- 给启动页添加加载状态(比如
CircularProgressIndicator),避免用户误以为App冻结。 - 不要在SharedPreference中存储明文密码,这属于严重安全问题,建议改用Firebase自带的持久化登录(
setPersistence),无需手动存储密码。
内容的提问来源于stack exchange,提问作者Mr Fin
相关产品推荐
相关产品推荐

