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

如何在Flutter中通过Firebase Firestore显示用户名与头像

问题背景

我已编写获取用户名和头像的代码,且成功获取到文档ID。终端输出如下:

Restarted application in 425ms.
flutter: DocumentReference<Map<String, dynamic>>(UserData/yKorLkbVK5jIGlWIti95)

UI部分已开发完成,界面效果:
UI界面

CloudFirestore数据结构:
CloudFirestore设置


代码文件

setting.dart

import 'dart:ffi';
import 'package:Meucci/FireAuth/getUserData.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';

class Setting extends StatefulWidget {
  const Setting({Key? key}) : super(key: key);

  @override
  State<Setting> createState() => _SettingState();
}

class _SettingState extends State<Setting> {
  final user = FirebaseAuth.instance.currentUser;

  List<String> documentID = [];

  Future getDocumentID() async {
    await FirebaseFirestore.instance.collection('UserData').get().then(
          (snapshot) => snapshot.docs.forEach((element) {
            print(element.reference);
            //documentID.add(element.reference.id);
          }),
        );
  }

  @override
  void initState() {
    getDocumentID();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: SafeArea(
      child: Center(
        child: Column(
          children: [
            SizedBox(height: 50),

            Stack(
              alignment: Alignment.bottomRight,
              children: [
                Container(
                  height: 150,
                  width: 150,
                  decoration: BoxDecoration(
                      shape: BoxShape.circle,
                      border: Border.all(color: Colors.purpleAccent, width: 3)),
                ),
                InkWell(
                  onTap: () {},
                  child: CircleAvatar(
                    child: Icon(Icons.edit, color: Colors.white),
                    backgroundColor: Colors.purpleAccent[100],
                  ),
                )
              ],
            ),
            SizedBox(height: 50),
            Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text('Signed In as: ' + user!.email!),
                Material(
                  child: MaterialButton(
                      onPressed: () {
                        FirebaseAuth.instance.signOut();
                      },
                      color: Colors.purpleAccent[100],
                      child: Text('Sign Out'),
                      shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(20.0))),
                )
              ],
            ),
          ],
        ),
      ),
    ));
  }
}

getUserData.dart

import 'package:flutter/material.dart';

class getUserData extends StatelessWidget {
  final String docId;
  getUserData({required this.docId});

  CollectionReference users = FirebaseFirestore.instance.collection('UserData');

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<DocumentSnapshot>(
      future: users.doc(docId).get(),
      builder: ((context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          Map<String, dynamic> data =
              snapshot.data!.data() as Map<String, dynamic>;
          return Text('${data['name']}');
        }
        return Text('Loading..');
      }),
    );
  }
}

技术问题及解决方案

1. 使用FutureBuilder展示用户名

首先要修正当前获取文档ID的逻辑(原方法遍历所有用户,应只获取当前登录用户的文档ID):

// 新增获取当前用户文档ID的方法
Future<String?> getCurrentUserDocId() async {
  final currentUser = FirebaseAuth.instance.currentUser;
  if (currentUser == null) return null;

  // 按邮箱匹配用户文档(如果文档用UID作为ID,直接return currentUser.uid即可)
  final snapshot = await FirebaseFirestore.instance
      .collection('UserData')
      .where('email', isEqualTo: currentUser.email)
      .get();
  return snapshot.docs.isNotEmpty ? snapshot.docs.first.id : null;
}

然后修改Setting组件的状态管理,结合FutureBuilder展示用户名:

class _SettingState extends State<Setting> {
  final user = FirebaseAuth.instance.currentUser;
  String? currentUserDocId;

  @override
  void initState() {
    super.initState();
    _fetchDocId();
  }

  Future<void> _fetchDocId() async {
    final id = await getCurrentUserDocId();
    setState(() => currentUserDocId = id);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: Column(
            children: [
              SizedBox(height: 50),
              // 头像区域(保留原代码)
              Stack(
                alignment: Alignment.bottomRight,
                children: [
                  Container(
                    height: 150,
                    width: 150,
                    decoration: BoxDecoration(
                        shape: BoxShape.circle,
                        border: Border.all(color: Colors.purpleAccent, width: 3)),
                  ),
                  InkWell(
                    onTap: () {},
                    child: CircleAvatar(
                      child: Icon(Icons.edit, color: Colors.white),
                      backgroundColor: Colors.purpleAccent[100],
                    ),
                  )
                ],
              ),
              SizedBox(height: 20),
              // 用户名展示
              currentUserDocId != null
                  ? getUserData(docId: currentUserDocId!)
                  : Text('加载中...'),
              SizedBox(height: 30),
              // 原有的邮箱和退出按钮区域
              Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Text('Signed In as: ' + user!.email!),
                  Material(
                    child: MaterialButton(
                        onPressed: () => FirebaseAuth.instance.signOut(),
                        color: Colors.purpleAccent[100],
                        child: Text('Sign Out'),
                        shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(20.0))),
                  )
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

2. 通过CloudFirestore的头像URL展示头像+用户名

先修改getUserData组件,使其能同时返回用户名和头像URL,或者直接在Setting组件中用FutureBuilder获取完整用户数据:

// 新增获取完整用户数据的工具函数
Future<Map<String, dynamic>?> fetchFullUserData(String docId) async {
  final snapshot = await FirebaseFirestore.instance.collection('UserData').doc(docId).get();
  return snapshot.exists ? snapshot.data() as Map<String, dynamic> : null;
}

然后重构Setting组件的build方法,整合头像和用户名展示:

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: SafeArea(
      child: Center(
        child: FutureBuilder<Map<String, dynamic>?>(
          future: currentUserDocId != null ? fetchFullUserData(currentUserDocId!) : null,
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return CircularProgressIndicator();
            }
            if (snapshot.hasError || snapshot.data == null) {
              return Text('加载用户信息失败');
            }

            final userData = snapshot.data!;
            final userName = userData['name'] ?? '未设置用户名';
            final avatarUrl = userData['avatar'] as String?;

            return Column(
              children: [
                SizedBox(height: 50),
                // 带头像的圆形容器
                Stack(
                  alignment: Alignment.bottomRight,
                  children: [
                    Container(
                      height: 150,
                      width: 150,
                      decoration: BoxDecoration(
                          shape: BoxShape.circle,
                          border: Border.all(color: Colors.purpleAccent, width: 3)),
                      child: avatarUrl != null
                          ? ClipOval(
                              child: Image.network(
                                avatarUrl,
                                fit: BoxFit.cover,
                                width: 150,
                                height: 150,
                                errorBuilder: (_, __, ___) => Icon(Icons.person, size: 80),
                              ),
                            )
                          : Icon(Icons.person, size: 80),
                    ),
                    InkWell(
                      onTap: () {},
                      child: CircleAvatar(
                        child: Icon(Icons.edit, color: Colors.white),
                        backgroundColor: Colors.purpleAccent[100],
                      ),
                    )
                  ],
                ),
                SizedBox(height: 20),
                // 头像下方的用户名
                Text(
                  userName,
                  style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                ),
                SizedBox(height: 30),
                // 原有的邮箱和退出按钮区域
                Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text('Signed In as: ' + user!.email!),
                    Material(
                      child: MaterialButton(
                          onPressed: () => FirebaseAuth.instance.signOut(),
                          color: Colors.purpleAccent[100],
                          child: Text('Sign Out'),
                          shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(20.0))),
                    )
                  ],
                ),
              ],
            );
          },
        ),
      ),
    ),
  );
}

内容的提问来源于stack exchange,提问作者Zephys

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 05:45:35