Flutter中如何从Firestore读取数据映射到UserModel?
问题解决:Firestore读取数据映射到UserModel失败
核心问题:Firestore中存储的time字段是Timestamp类型,你的UserModel.fromJson方法直接将其赋值给DateTime类型变量,导致类型转换错误。
以下是修正后的完整代码:
1. 修正UserModel.dart
class UserModel { String? name; String? bio; String? dpUrl; String? email; String? uid; DateTime? time; List<String>? followers; List<String>? followings; UserModel({ required this.name, required this.bio, required this.dpUrl, required this.email, required this.uid, required this.time, required this.followers, required this.followings, }); // 修复Timestamp转DateTime的逻辑 UserModel.fromJson(Map<String, dynamic> json) { name = json['name']; bio = json['bio']; dpUrl = json['dpUrl']; email = json['email']; uid = json['uid']; // 判断是否为Timestamp类型,转换为DateTime if (json['time'] is Timestamp) { time = (json['time'] as Timestamp).toDate(); } else { // 兼容其他可能的时间格式(比如字符串) time = DateTime.tryParse(json['time'].toString()); } followers = json['followers']?.cast<String>() ?? []; followings = json['followings']?.cast<String>() ?? []; } Map<String, dynamic> toJson() { final Map<String, dynamic> data = <String, dynamic>{}; data['name'] = name; data['bio'] = bio; data['dpUrl'] = dpUrl; data['email'] = email; data['uid'] = uid; // 存回Firestore时转成Timestamp data['time'] = time != null ? Timestamp.fromDate(time!) : null; data['followers'] = followers; data['followings'] = followings; return data; } }
2. 修正Database类
取消readUser方法的注释,并添加空值防护:
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter_say/model/user_model.dart'; class Database { final String? uid; Database({required this.uid}); final userdataRef = FirebaseFirestore.instance.collection('userdata'); Future<UserModel?> readUser() async { // 先判断uid是否为空,避免无效请求 if (uid == null || uid!.isEmpty) { return null; } final docUser = userdataRef.doc(uid); final snapshot = await docUser.get(); if (snapshot.exists && snapshot.data() != null) { return UserModel.fromJson(snapshot.data()!); } return null; } }
3. 修正ProfilePage.dart
处理snapshot.data为null的情况,避免空指针异常:
import 'package:flutter/material.dart'; import 'package:flutter_say/model/user_model.dart'; import 'package:flutter_say/services/database.dart'; class ProfilePage extends StatefulWidget { final String uid; const ProfilePage({ super.key, required this.uid, }); @override State<ProfilePage> createState() => _ProfilePageState(); } class _ProfilePageState extends State<ProfilePage> { @override Widget build(BuildContext context) { return FutureBuilder<UserModel?>( future: Database(uid: widget.uid).readUser(), builder: (context, snapshot) { if (snapshot.hasError) { return Center( child: Text('错误:${snapshot.error.toString()}'), // 显示具体错误信息便于排查 ); } if (snapshot.connectionState == ConnectionState.waiting) { return const Center( child: CircularProgressIndicator(), ); } final userData = snapshot.data; if (userData == null) { return const Center( child: Text('用户数据不存在'), ); } return SafeArea( child: ListTile( title: Text('Name - ${userData.name ?? "未设置"}'), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Bio - ${userData.bio ?? "无简介"}'), Text('邮箱 - ${userData.email ?? "未绑定"}'), ], ), leading: userData.dpUrl != null ? CircleAvatar(backgroundImage: NetworkImage(userData.dpUrl!)) : const CircleAvatar(child: Icon(Icons.person)), ), ); }, ); } }
额外排查点
- 确认Firestore的
userdata集合中,存在以当前用户uid命名的文档,且字段名(如name、dpUrl、time)与UserModel中的键完全一致(大小写敏感)。 - 检查Firestore安全规则,确保当前用户有权限读取
userdata集合中的文档。 - 运行前先清理项目缓存(
flutter clean)并重新构建。
内容的提问来源于stack exchange,提问作者Neal
相关产品推荐
相关产品推荐

