Flutter接入Firebase登录时设置用户名头像及后续获取问题求解
问题根因
- 你将
authStateChanges监听放在了build方法中,注册操作调用createUserWithEmailAndPassword完成后会立即触发Auth状态变更,直接跳转到Home页,此时后续的头像上传、Firestore用户数据写入、Auth Profile更新操作还未执行完成,被页面跳转中断,导致用户名等数据没有正常写入存储。 - 头像存储路径拼写错误,缺少
.jpg后缀的分隔点,可能导致头像上传后无法正常拉取。 - 注册流程未同步更新Firebase Auth内置的用户Profile字段,后续无法直接通过Auth实例快速获取用户名和头像。
修复方案
1. 调整监听位置与跳转逻辑
将authStateChanges监听从build方法移到initState中,仅用于APP冷启动时判断用户登录状态自动跳转;注册/登录操作完成后手动控制跳转,避免提前跳转打断异步写入操作。
修改_WelcomeScreenState代码:
@override void initState() { super.initState(); // 把auth状态监听移到这里,仅冷启动时触发自动登录 FirebaseAuth.instance .authStateChanges() .listen((User? user) { if (user != null && mounted) { _completeLogin(); } }); controller = AnimationController ( duration: Duration(seconds: 1), vsync: this, ); animation = ColorTween(begin: Colors.transparent, end: Colors.white.withOpacity(0.5)).animate(controller); controller.forward(); controller.addListener(() { setState(() {}); }); } @override Widget build(BuildContext context) { // 移除原来在这里的authStateChanges监听 return Container( // 原来的build代码不变 decoration: BoxDecoration( image: DecorationImage( image: AssetImage("images/bar1.jpg"), fit: BoxFit.fill, ) ), child: Scaffold( backgroundColor: Colors.white.withOpacity(0.5), body: Container( child: Center( child: SingleChildScrollView( child: Column( children: <Widget>[ Image.asset('assets/images/logo.png'), AuthForm( _submitAuthForm, _isLoading, ), ], ), ), ), ), ), ); }
2. 修复注册流程的异步逻辑
修改_submitAuthForm方法,补全等待写入完成、更新Auth Profile、手动跳转、重置加载状态的逻辑,同时修正头像路径拼写错误:
void _submitAuthForm( String email, String username, String password, File imageFile, bool isLogin, BuildContext ctx, ) async { UserCredential authResult; try { setState(() { _isLoading = true; }); if (isLogin) { authResult = await _auth.signInWithEmailAndPassword( email: email, password: password, ); // 登录完成手动跳转 if (mounted) _completeLogin(); } else { authResult = await _auth.createUserWithEmailAndPassword( email: email, password: password, ); // 修正头像路径的拼写错误,加.分隔后缀 final ref = FirebaseStorage.instance .ref() .child('user_image') .child(authResult.user!.uid + '.jpg'); await ref.putFile(imageFile); final url = await ref.getDownloadURL(); // 同步更新Firebase Auth的用户Profile await authResult.user?.updateDisplayName(username); await authResult.user?.updatePhotoURL(url); await authResult.user?.reload(); // 写入用户数据到Firestore await FirebaseFirestore.instance .collection('users') .doc(authResult.user!.uid) .set({ 'username': username, 'email': email, 'image_url': url, }); // 所有写入操作完成后再手动跳转 if (mounted) _completeLogin(); } } on FirebaseAuthException catch (error) { var message = '发生错误,请检查你的输入信息'; if (error.message != null) { message = error.message!; } if (mounted) ScaffoldMessenger.of(ctx).showSnackBar(SnackBar(content: Text(message))); } finally { // 无论成功失败都重置加载状态 if (mounted) { setState(() { _isLoading = false; }); } } }
后续页面拉取展示用户信息的方法
方法1:直接从Firebase Auth实例获取(推荐,速度快)
// 任意需要展示用户信息的页面调用 final currentUser = FirebaseAuth.instance.currentUser; String? displayName = currentUser?.displayName ?? '匿名用户'; String? avatarUrl = currentUser?.photoURL; // 展示示例 @override Widget build(BuildContext context) { return Row( children: [ CircleAvatar( backgroundImage: avatarUrl != null ? NetworkImage(avatarUrl) : null, child: avatarUrl == null ? const Icon(Icons.person) : null, ), const SizedBox(width: 8), Text(displayName), ], ); }
方法2:从Firestore查询全量用户信息
如果需要获取除了用户名、头像之外的其他自定义用户字段,可以从Firestore拉取:
Future<Map<String, dynamic>?> getUserData() async { final uid = FirebaseAuth.instance.currentUser?.uid; if (uid == null) return null; final doc = await FirebaseFirestore.instance.collection('users').doc(uid).get(); return doc.data(); } // 使用时 getUserData().then((userData) { if (userData != null) { String username = userData['username']; String avatarUrl = userData['image_url']; // 其他字段自行取值 } });
内容的提问来源于stack exchange,提问作者flutterloop
相关产品推荐
相关产品推荐

