使用Google登录向Cloud Firestore存数据时遇组件祖先不安全错误
解决Flutter中“Looking up a deactivated widget's ancestor is unsafe”错误
错误原因
异步登录操作(signInWithGoogle)完成后,传入的context对应的Widget可能已经被销毁(比如用户返回页面、触发跳转),此时用该context调用showSnackBar会尝试访问已失效的Widget树节点,从而抛出错误。
解决方案
方案1:使用GlobalKey获取Scaffold状态
通过全局Key绑定Scaffold,避免依赖可能失效的context:
- 在页面组件中定义GlobalKey:
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
- 将Key绑定到Scaffold:
Scaffold( key: _scaffoldKey, // 其他页面内容 )
- 修改登录方法,使用GlobalKey显示SnackBar:
void signInWithGoogle(GlobalKey<ScaffoldState> scaffoldKey, bool isFromLogin) async { state = true; final user = await _authRepository.signInWithGoogle(isFromLogin); state = false; user.fold( (l) { if (scaffoldKey.currentContext != null) { showSnackBar(scaffoldKey.currentContext!, l.message); } }, (userModel) => _ref.read(userProvider.notifier).update((state) => userModel), ); }
方案2:检查Widget挂载状态(StatefulWidget场景)
如果登录方法属于State类,先通过mounted属性判断Widget是否仍存活:
void signInWithGoogle(BuildContext context, bool isFromLogin) async { state = true; final user = await _authRepository.signInWithGoogle(isFromLogin); state = false; // 确保Widget未被销毁 if (!mounted) return; user.fold( (l) => showSnackBar(context, l.message), (userModel) => _ref.read(userProvider.notifier).update((state) => userModel), ); }
方案3:使用ScaffoldMessenger安全显示SnackBar(Flutter 2.0+)
利用ScaffoldMessenger替代直接调用showSnackBar,并捕获可能的异常:
void signInWithGoogle(BuildContext context, bool isFromLogin) async { state = true; final user = await _authRepository.signInWithGoogle(isFromLogin); state = false; user.fold( (l) { try { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(l.message)), ); } catch (_) {} }, (userModel) => _ref.read(userProvider.notifier).update((state) => userModel), ); }
内容的提问来源于stack exchange,提问作者Jabu
相关产品推荐
相关产品推荐

