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

Flutter中如何读取Firestore用户文档字段并填充TextFormField

问题原因

你当前编写的getPatientData()方法仅返回了Firestore的文档引用(DocumentReference)对象,没有实际发起请求拉取文档内存储的字段数据,这是无法读取用户信息填充输入框的核心原因。

实现步骤
  • 为每个输入框创建TextEditingController,用于控制输入框的文本赋值、内容获取
  • 修正数据获取逻辑:拿到文档引用后调用get()方法拉取实际文档快照,从快照的data()属性中读取各字段值
  • 在页面初始化阶段触发数据拉取,数据返回后给对应controller赋值,同时加入加载状态避免空数据报错
  • 页面销毁时释放所有controller,避免内存泄漏
完整代码示例
class PatientInfoPage extends StatefulWidget {
  const PatientInfoPage({super.key});

  @override
  State<PatientInfoPage> createState() => _PatientInfoPageState();
}

class _PatientInfoPageState extends State<PatientInfoPage> {
  // 为每个输入框初始化对应控制器
  final _fullNameController = TextEditingController();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  final _phoneController = TextEditingController();
  bool _isLoading = true;

  // 修正后的用户数据拉取方法
  Future<void> getPatientData() async {
    try {
      // 调用get()拉取实际文档数据
      DocumentSnapshot patientDoc = await FirebaseFirestore.instance
          .collection('Users')
          .doc('PatientData')
          .collection('Patients')
          .doc(FirebaseAuth.instance.currentUser!.uid)
          .get();
      
      if (patientDoc.exists) {
        Map<String, dynamic> patientData = patientDoc.data() as Map<String, dynamic>;
        // 给控制器赋值,输入框会自动同步显示内容
        // 注意:字段名必须和Firestore中存储的键名完全一致,大小写敏感
        _fullNameController.text = patientData['fullName'] ?? '';
        _emailController.text = patientData['email'] ?? '';
        _passwordController.text = patientData['password'] ?? '';
        _phoneController.text = patientData['phoneNumber'] ?? '';
      }
    } catch (e) {
      // 可自行添加错误提示逻辑,比如通过SnackBar展示报错信息
      debugPrint('获取用户数据失败: $e');
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  @override
  void initState() {
    super.initState();
    // 页面初始化时触发数据拉取
    getPatientData();
  }

  @override
  void dispose() {
    // 销毁控制器释放资源
    _fullNameController.dispose();
    _emailController.dispose();
    _passwordController.dispose();
    _phoneController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // 数据加载中展示加载态
    if (_isLoading) {
      return const Center(child: CircularProgressIndicator(color: Colors.green));
    }
    // 数据加载完成后展示表单
    return ListView(
      children: [
        Container(
          padding: const EdgeInsets.all(10),
          child: TextFormField(
            controller: _fullNameController,
            decoration: InputDecoration(
              labelText: 'Full Name',
              enabledBorder: OutlineInputBorder(
                  borderSide:
                      const BorderSide(color: Colors.green, width: 2.0),
                  borderRadius: BorderRadius.circular(15.0)),
              focusedBorder: OutlineInputBorder(
                borderSide: const BorderSide(color: Colors.green, width: 2.0),
                borderRadius: BorderRadius.circular(15.0),
              ),
            ),
          ),
        ),
        Container(
          padding: const EdgeInsets.all(10),
          child: TextFormField(
            controller: _emailController,
            decoration: InputDecoration(
              labelText: 'Email',
              enabledBorder: OutlineInputBorder(
                  borderSide:
                      const BorderSide(color: Colors.green, width: 2.0),
                  borderRadius: BorderRadius.circular(15.0)),
              focusedBorder: OutlineInputBorder(
                borderSide: const BorderSide(color: Colors.green, width: 2.0),
                borderRadius: BorderRadius.circular(15.0),
              ),
            ),
          ),
        ),
        Container(
          padding: const EdgeInsets.all(10),
          child: TextFormField(
            controller: _passwordController,
            obscureText: true,
            decoration: InputDecoration(
              labelText: 'Password',
              enabledBorder: OutlineInputBorder(
                  borderSide:
                      const BorderSide(color: Colors.green, width: 2.0),
                  borderRadius: BorderRadius.circular(15.0)),
              focusedBorder: OutlineInputBorder(
                borderSide: const BorderSide(color: Colors.green, width: 2.0),
                borderRadius: BorderRadius.circular(15.0),
              ),
            ),
          ),
        ),
        Container(
          padding: const EdgeInsets.all(10),
          child: TextFormField(
            controller: _phoneController,
            keyboardType: TextInputType.phone,
            decoration: InputDecoration(
              labelText: 'Phone Number',
              enabledBorder: OutlineInputBorder(
                  borderSide:
                      const BorderSide(color: Colors.green, width: 2.0),
                  borderRadius: BorderRadius.circular(15.0)),
              focusedBorder: OutlineInputBorder(
                borderSide: const BorderSide(color: Colors.green, width: 2.0),
                borderRadius: BorderRadius.circular(15.0),
              ),
            ),
          ),
        ),
      ],
    );
  }
}
注意事项
  • 读取字段时的键名必须和Firestore文档中存储的字段名完全一致,大小写敏感,如果赋值为空优先检查键名是否匹配
  • 代码中用?? ''做空值兜底,避免Firestore中对应字段不存在时赋值null引发报错
  • 示例中给密码框加了密文显示、手机号框加了数字键盘类型,符合常规交互逻辑,可根据需求调整
  • 后续如果需要提交修改后的用户数据,直接读取对应controller的text属性即可拿到输入框的最新值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 05:12:16