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

如何在Flutter的CategorySelector中获取Firestore当前用户信息并展示?

解决CategorySelector中获取Firestore用户信息与Storage头像的问题

我来帮你梳理下完整的实现逻辑,咱们一步步来搞定:

1. 先修复AuthenticationService的getCurrentUser方法

首先得确保能正确拿到当前登录用户的UID,这是后续所有操作的基础。如果你的getCurrentUser没达到预期,大概率是没做好用户状态监听或者返回值逻辑有问题,调整成这样更可靠:

class AuthenticationService {
  final FirebaseAuth _auth = FirebaseAuth.instance;

  // 推荐用Stream实时监听用户登录/退出状态变化
  Stream<User?> get userStream => _auth.authStateChanges();

  // 同步获取当前用户(适合一次性场景,但不如Stream实时)
  User? getCurrentUser() {
    return _auth.currentUser;
  }
}

这里优先用userStream,因为用户可能随时切换登录状态,Stream能自动触发UI更新,比单次调用getCurrentUser更灵活。

2. 在CategorySelector中整合数据获取逻辑

接下来在你的CategorySelector组件里,我们用StreamBuilder监听用户状态,一旦用户登录成功,就并行从Firestore拉取用户信息、从Storage获取头像URL:

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

  @override
  State<CategorySelector> createState() => _CategorySelectorState();
}

class _CategorySelectorState extends State<CategorySelector> {
  final AuthenticationService _authService = AuthenticationService();
  final DatabaseManager _dbManager = DatabaseManager();

  // 从Storage获取用户头像下载URL
  Future<String?> _fetchUserAvatar(String userId) async {
    try {
      final avatarRef = FirebaseStorage.instance.ref().child('user_avatars/$userId.jpg');
      return await avatarRef.getDownloadURL();
    } catch (e) {
      print('加载头像失败: $e');
      // 头像不存在时返回null,后续用默认头像兜底
      return null;
    }
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<User?>(
      stream: _authService.userStream,
      builder: (context, authSnapshot) {
        if (authSnapshot.connectionState == ConnectionState.waiting) {
          // 等待用户状态加载时显示加载圈
          return const CircularProgressIndicator();
        }

        if (!authSnapshot.hasData || authSnapshot.data == null) {
          // 用户未登录时,显示提示或跳转登录页
          return const Text('请先登录');
        }

        final currentUserId = authSnapshot.data!.uid;

        // 并行请求用户数据和头像URL,提升加载效率
        return FutureBuilder<Map<String, dynamic>?>(
          future: Future.wait([
            _dbManager.getUserData(currentUserId),
            _fetchUserAvatar(currentUserId)
          ]).then((results) => {
            'user': results[0],
            'avatarUrl': results[1]
          }),
          builder: (context, dataSnapshot) {
            if (dataSnapshot.connectionState == ConnectionState.waiting) {
              return const CircularProgressIndicator();
            }

            if (!dataSnapshot.hasData || dataSnapshot.data == null) {
              return const Text('加载用户信息失败');
            }

            final userModel = dataSnapshot.data!['user'] as UserModel;
            final avatarUrl = dataSnapshot.data!['avatarUrl'] as String?;

            // 渲染用户名和头像
            return Row(
              children: [
                CircleAvatar(
                  radius: 22,
                  backgroundImage: avatarUrl != null
                      ? NetworkImage(avatarUrl)
                      : const AssetImage('assets/default_avatar.png') as ImageProvider,
                ),
                const SizedBox(width: 12),
                Text(
                  userModel.username, // 假设你的User模型有username字段
                  style: const TextStyle(
                    fontSize: 16,
                    fontWeight: FontWeight.w600
                  ),
                )
              ],
            );
          },
        );
      },
    );
  }
}

3. 确保DatabaseManager的getUserData方法正确实现

你的DatabaseManager需要有一个根据UID从Firestore拉取用户数据的方法,示例如下:

class DatabaseManager {
  final FirebaseFirestore _firestore = FirebaseFirestore.instance;

  Future<UserModel?> getUserData(String userId) async {
    try {
      final userDoc = await _firestore.collection('users').doc(userId).get();
      if (userDoc.exists) {
        // 将Firestore文档数据映射到你的User模型
        return UserModel.fromMap(userDoc.data()!);
      }
      return null;
    } catch (e) {
      print('获取用户数据出错: $e');
      return null;
    }
  }
}

几个关键注意点

  • 状态监听优先级:用StreamBuilder监听用户状态,能自动处理登录/退出后的UI更新,比手动调用getCurrentUser更稳定。
  • 异步优化:用Future.wait并行请求用户数据和头像,避免串行请求导致的加载延迟。
  • 错误兜底:一定要加try-catch处理网络异常、数据不存在的情况,同时给头像设置默认图,避免UI崩溃。

这样调整后,你的CategorySelector就能正确展示当前登录用户的用户名和头像啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:00:06