Flutter中使用StreamBuilder从Firestore拉取用户姓名失败问题排查
问题分析与修复方案
我看了你的代码,发现几个关键问题导致Firestore的数据没显示出来,反而还是显示硬编码的名字:
1. 你没有在界面中使用ProfileWidget组件
你已经写了用来读取Firestore数据的ProfileWidget,但在MyHomePage的界面里,你仍然直接用硬编码的Text('Eric Schmidt'),完全没把ProfileWidget加到布局中,自然不会触发Firestore数据读取。
2. User类的name字段类型错误
Firestore里存储的姓名应该是字符串类型,但你把User类的name定义成了int,这会导致解析数据时隐性失败(虽然没有报错,但无法正确读取姓名内容)。
3. 缺少用户ID的传递
你需要确保传递给ProfileWidget的userId是Firestore中users集合里真实存在的文档ID,否则会读不到目标用户的数据。
修改后的完整代码
import 'package:flutter/material.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'dart:ui' as ui; void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: 'Profile Demo', theme: new ThemeData( primarySwatch: Colors.blue, ), home: new MyHomePage(title: 'Profile'), ); } } class ProfileWidget extends StatelessWidget { final String userId; ProfileWidget(this.userId); @override Widget build(BuildContext context) { return StreamBuilder<DocumentSnapshot>( stream: FirebaseFirestore.instance.collection('users').doc(userId).snapshots(), builder: (context, snapshot) { // 处理错误情况 if (snapshot.hasError) { return Text('读取数据出错: ${snapshot.error}', style: TextStyle(color: Colors.white)); } // 处理加载状态 if (snapshot.connectionState == ConnectionState.waiting) { return CircularProgressIndicator(color: Colors.white); } // 读取到有效数据时渲染 if (snapshot.hasData && snapshot.data!.exists) { User user = User.fromSnapshot(snapshot.data!); return Text( user.name, style: new TextStyle( fontWeight: FontWeight.bold, fontSize: MediaQuery.of(context).size.width / 15, color: Colors.white), ); } else { return Text('用户不存在', style: TextStyle(color: Colors.white)); } }); } } class User { final String name; // 修正为String类型,匹配Firestore存储的姓名格式 final DocumentReference? reference; User.fromMap(Map<String, dynamic> map, {this.reference}) : name = map['name'] as String; User.fromSnapshot(DocumentSnapshot snapshot) : this.fromMap(snapshot.data() as Map<String, dynamic>, reference: snapshot.reference); } class MyHomePage extends StatefulWidget { MyHomePage({Key? key, this.title}) : super(key: key); final String? title; @override _MyHomePageState createState() => new _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { // 替换成你Firestore中users集合里实际存在的文档ID final String currentUserId = 'your-target-user-id'; @override Widget build(BuildContext context) { final _width = MediaQuery.of(context).size.width; final _height = MediaQuery.of(context).size.height; final String imgUrl = 'https://pixel.nymag.com/imgs/daily/selectall/2017/12/26/26-eric-schmidt.w700.h700.jpg'; return new Stack( children: <Widget>[ new Container( color: Colors.blue, ), new Image.network( imgUrl, fit: BoxFit.fill, ), new BackdropFilter( filter: new ui.ImageFilter.blur( sigmaX: 6.0, sigmaY: 6.0, ), child: new Container( decoration: BoxDecoration( color: Colors.blue.withOpacity(0.9), borderRadius: BorderRadius.all(Radius.circular(50.0)), ), )), new Scaffold( appBar: new AppBar( title: new Text(widget.title!), centerTitle: false, elevation: 0.0, backgroundColor: Colors.transparent, ), drawer: new Drawer( child: new Container(), ), backgroundColor: Colors.transparent, body: new Center( child: new Column( children: <Widget>[ new SizedBox( height: _height / 12, ), new CircleAvatar( radius: _width < _height ? _width / 4 : _height / 4, backgroundImage: NetworkImage(imgUrl), ), new SizedBox( height: _height / 25.0, ), // 替换硬编码文本为ProfileWidget,传入目标用户ID ProfileWidget(currentUserId), new Padding( padding: new EdgeInsets.only( top: _height / 30, left: _width / 8, right: _width / 8), child: new Text( 'Snowboarder, Superhero and writer.\nSometime I work at google as Executive Chairman ', style: new TextStyle( fontWeight: FontWeight.normal, fontSize: _width / 25, color: Colors.white), textAlign: TextAlign.center, ), ), new Divider( height: _height / 30, color: Colors.white, ), new Row( children: <Widget>[ rowCell(343, 'POSTS'), rowCell(673826, 'FOLLOWERS'), rowCell(275, 'FOLLOWING'), ], ), new Divider(height: _height / 30, color: Colors.white), new Padding( padding: new EdgeInsets.only( left: _width / 8, right: _width / 8), child: new FlatButton( onPressed: () {}, child: new Container( child: new Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ new Icon(Icons.person), new SizedBox( width: _width / 30, ), new Text('FOLLOW') ], )), color: Colors.blue[50], ), ), ], ), )) ], ); } Widget rowCell(int count, String type) => new Expanded( child: new Column( children: <Widget>[ new Text( '$count', style: new TextStyle(color: Colors.white), ), new Text(type, style: new TextStyle( color: Colors.white, fontWeight: FontWeight.normal)) ], )); }
额外注意事项
- 务必把
currentUserId替换成你Firestore中users集合里真实存在的文档ID,否则会显示"用户不存在"。 - 确保Firestore安全规则允许读取
users集合的数据(测试阶段可暂时设置为开放规则,上线前必须修改为符合业务逻辑的安全规则)。 - 代码中更新了Firestore的API调用为最新版本写法,如果你使用的是旧版
cloud_firestore包,可以改回Firestore.instance.document()的写法,但建议升级到最新包版本。
内容的提问来源于stack exchange,提问作者James Roth
相关产品推荐
相关产品推荐

