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

Flutter中Firestore获取role字段触发Bad state异常问题排查

问题描述

我在Firestore中创建了Users集合,每个文档包含name、email、password、phone、role字段,想通过获取role字段实现Flutter应用中普通用户和管理员跳转至不同仪表盘的功能,但运行代码时抛出异常:

Exception has occurred. StateError (Bad state: cannot get a field on a DocumentSnapshotPlatform which does not exist)

Firestore数据库说明:Users集合下的文档以用户UID为文档ID,每个文档包含上述5个字段,role字段值为user或admin。

相关代码:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:role_base_app/Views/admin_dashboard.dart';
import 'package:role_base_app/Views/user_dashboard.dart';

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: const Text("Home"),
        ),
        body: StreamBuilder<User?>(
          stream: FirebaseAuth.instance.authStateChanges(),
          builder: (context, snapshot) {
            if (snapshot.hasData && snapshot.data != null) {
              return StreamBuilder(
                stream: FirebaseFirestore.instance
                    .collection("Users")
                    .doc(snapshot.data!.uid)
                    .snapshots(),
                builder: (BuildContext context,
                    AsyncSnapshot<DocumentSnapshot> snapshot) {
                  if (snapshot.hasData && snapshot.data != null) {
                    final user = snapshot.data!;
                    // devtools.log(user.toString());
                    if (user['role'] == 'user') {
                      return const UserDashboard();
                    } else {
                      return const AdminDashboard();
                    }
                  }
                  return const Text("Done");
                },
              );
            }
            return const Text("well Done");
          },
        ),
      ),
    );
  }
}
解决方案
  • 检查文档与字段的正确性
    确认Users集合下,当前登录用户UID对应的文档确实存在,且role字段拼写完全一致(Firestore字段名大小写敏感,别写成Role或ROLE)。可以在代码中临时添加print(user.data());打印文档所有字段,确认role是否存在。

  • 安全访问字段,避免直接下标取值
    直接用user['role']会在字段不存在时抛出异常,改用安全取值方式:

    final userData = user.data() as Map<String, dynamic>;
    final role = userData['role']; // 或者用user.get('role', defaultValue: null)
    
    if (role == 'user') {
      return const UserDashboard();
    } else if (role == 'admin') {
      return const AdminDashboard();
    } else {
      // 处理角色不存在或未知的情况
      return const Text('用户角色未设置,请联系管理员');
    }
    
  • 验证Firestore权限规则
    确保当前用户有权限读取自己的文档,在Firebase控制台的Firestore规则中设置:

    rules_version = '2';
    service cloud.firestore {
      match /databases/{database}/documents {
        match /Users/{userId} {
          allow read, write: if request.auth != null && request.auth.uid == userId;
        }
      }
    }
    
  • 完善快照状态处理
    原代码未处理加载状态和错误情况,补充后避免过早访问数据:

    builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
      if (snapshot.connectionState == ConnectionState.waiting) {
        return const CircularProgressIndicator();
      }
      if (snapshot.hasError) {
        return Text('加载失败: ${snapshot.error}');
      }
      // 确认文档存在
      if (!snapshot.hasData || !snapshot.data!.exists) {
        return const Text('未找到用户信息,请完善资料');
      }
      
      final userData = snapshot.data!.data() as Map<String, dynamic>;
      final role = userData['role'];
      if (role == 'user') {
        return const UserDashboard();
      } else if (role == 'admin') {
        return const AdminDashboard();
      } else {
        return const Text('未知用户角色');
      }
    },
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 20:57:04