You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter接入Firebase登录时设置用户名头像及后续获取问题求解

问题根因

  1. 你将authStateChanges监听放在了build方法中,注册操作调用createUserWithEmailAndPassword完成后会立即触发Auth状态变更,直接跳转到Home页,此时后续的头像上传、Firestore用户数据写入、Auth Profile更新操作还未执行完成,被页面跳转中断,导致用户名等数据没有正常写入存储。
  2. 头像存储路径拼写错误,缺少.jpg后缀的分隔点,可能导致头像上传后无法正常拉取。
  3. 注册流程未同步更新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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 04:54:01