Flutter迁移后创建组时currentUser为空,类型转换错误求助
问题:Flutter迁移后创建组时currentUser类型转换报错(Null转UserModel)
我正在开发一个通过groupID创建和加入组的项目,Flutter迁移后,用户创建组时出现currentUser相关的类型转换错误,Null无法转为UserModel。添加了null判断但问题依旧。
错误栈信息
Syncing files to device MO 01K... I/flutter (15786): the user uid is Fts7cm617ShS79JxqGRUOdsz7zo2 Reloaded 1 of 2161 libraries in 3,199ms (compile: 176 ms, reload: 1313 ms, reassemble: 1238 ms). I/flutter (15786): the user uid is Fts7cm617ShS79JxqGRUOdsz7zo2 I/flutter (15786): User is available! E/flutter (15786): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'Null' is not a subtype of type 'UserModel' in type cast E/flutter (15786): #0 _OurAddBookState._addBook (package:jattendence/Admin/screens/addBook/addBook.dart:108:64) E/flutter (15786): #1 _OurAddBookState.build.<anonymous closure> (package:jattendence/Admin/screens/addBook/addBook.dart:240:25) E/flutter (15786): #2 _InkResponseState.handleTap (package:flutter/src/material/ink_well.dart:1072:21) E/flutter (15786): #3 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:253:24)
UserModel类代码
import 'package:cloud_firestore/cloud_firestore.dart'; class UserModel { String? uid; String? email; Timestamp? accountCreated; String? fullName; String? groupId; String? notifToken; UserModel({ this.uid, this.email, this.accountCreated, this.fullName, this.groupId, this.notifToken, }); UserModel.fromDocumentSnapshot({required DocumentSnapshot <Map<String,dynamic>> doc}) { uid = doc.id; email = doc.data()?['email']; accountCreated = doc.data()?['accountCreated']; fullName = doc.data()?['fullName']; groupId = doc.data()?['groupId']; notifToken = doc.data()?['notifToken']; } }
创建组时调用currentUser的相关代码
class OurAddBook extends StatefulWidget { final bool? onGroupCreation; final bool? onError; final String? groupName; final UserModel? currentUser; OurAddBook({ this.onGroupCreation, this.onError, this.groupName, this.currentUser, }); @override _OurAddBookState createState() => _OurAddBookState(); } class _OurAddBookState extends State<OurAddBook> { final addBookKey = GlobalKey<ScaffoldState>(); TextEditingController _bookNameController = TextEditingController(); TextEditingController _authorController = TextEditingController(); TextEditingController _lengthController = TextEditingController(); DateTime _selectedDate = DateTime.now(); initState() { super.initState(); _selectedDate = DateTime(_selectedDate.year, _selectedDate.month, _selectedDate.day, _selectedDate.hour, 0, 0, 0, 0); } Future<void> _selectDate() async { final DateTime? picked = await showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime.now(), lastDate: DateTime(2222)); if (picked != null && picked != _selectedDate) { setState(() { _selectedDate = DateTime(picked.year, picked.month, picked.day, _selectedDate.hour, 0, 0, 0, 0); }); } } Future _selectTime() async { await showDialog<int>( context: context, builder: (BuildContext context) { int _currentIntValue = 0; return NumberPicker( value: _currentIntValue, minValue: 0, maxValue: 23, infiniteLoop: true, onChanged: (int value) { }, ); }, ).then(( value) { if (value != null) { setState(() { _selectedDate = DateTime(_selectedDate.year, _selectedDate.month, _selectedDate.day, value, 0, 0, 0, 0); }); } }); } void _addBook(BuildContext context, String? groupName, BookModel? book) async { String _returnString; if (_selectedDate.isAfter(DateTime.now().add(Duration(days: 1)))) { if (widget.currentUser == null) { print('current user not available'); } else { print('User is available!'); if (widget.onGroupCreation!) { _returnString = await DBFuture().createGroup( groupName!, widget.currentUser?.getCurrentUser as UserModel, book!); // 报错位置 } else if (widget.onError!) { _returnString = await DBFuture().addCurrentBook( widget.currentUser?.groupId as String, book!); } else { _returnString = await DBFuture().addNextBook( widget.currentUser?.groupId as String, book!); } if (_returnString == "success") { Navigator.pushAndRemoveUntil( context, MaterialPageRoute( builder: (context) => OurRoot(), ), (route) => false); } } } } }
我试过StackOverflow旧方案、Firestore 2.0迁移文档,用FirebaseAuth也没解决。现在需要正确获取Firestore中当前用户的UserModel信息来完成组创建。
解决方案
1. 定位核心问题
报错行widget.currentUser?.getCurrentUser as UserModel存在两个致命问题:
getCurrentUser方法在你的UserModel类中未定义,调用后必然返回null- 强行用
as UserModel转换null,直接触发类型转换异常
你虽然做了widget.currentUser == null的判断,但后续调用不存在的方法导致结果为null,绕过了判断逻辑引发报错。
2. 修复步骤
步骤1:移除不存在的方法调用
widget.currentUser本身就是UserModel类型,直接传入即可,无需调用不存在的getCurrentUser:
// 替换报错行 _returnString = await DBFuture().createGroup( groupName!, widget.currentUser!, book!);
步骤2:完善全链路null安全检查
避免强制解包引发的空指针,对所有必要参数做非空校验:
void _addBook(BuildContext context, String? groupName, BookModel? book) async { String _returnString; if (_selectedDate.isAfter(DateTime.now().add(Duration(days: 1)))) { // 先校验核心参数非空 if (widget.currentUser == null) { print('current user not available'); return; } if (widget.onGroupCreation == null || groupName == null || book == null) { print('缺少创建组的必要参数'); return; } print('User is available!'); if (widget.onGroupCreation!) { _returnString = await DBFuture().createGroup( groupName, widget.currentUser!, book); } else if (widget.onError == true) { if (widget.currentUser!.groupId == null) { print('用户groupId为空'); return; } _returnString = await DBFuture().addCurrentBook( widget.currentUser!.groupId!, book); } else { if (widget.currentUser!.groupId == null) { print('用户groupId为空'); return; } _returnString = await DBFuture().addNextBook( widget.currentUser!.groupId!, book); } if (_returnString == "success") { Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (context) => OurRoot()), (route) => false); } } }
步骤3:确保currentUser正确传入页面
如果widget.currentUser本身就是null,说明页面跳转时没有正确传递用户数据。需要在跳转前从Firebase拉取完整的UserModel:
// 示例:从FirebaseAuth获取uid,再从Firestore拉取用户数据 final firebaseUser = FirebaseAuth.instance.currentUser; if (firebaseUser != null) { final doc = await FirebaseFirestore.instance.collection('users').doc(firebaseUser.uid).get(); final userModel = UserModel.fromDocumentSnapshot(doc: doc); Navigator.push(context, MaterialPageRoute( builder: (context) => OurAddBook(currentUser: userModel, ...) )); }
步骤4:优化UserModel的空安全(可选)
给UserModel的核心字段添加非空约束,或在解析时处理空值,避免后续使用时出现意外null:
// 修改构造函数,确保uid非空 UserModel({ required this.uid, this.email, this.accountCreated, this.fullName, this.groupId, this.notifToken, }); UserModel.fromDocumentSnapshot({required DocumentSnapshot <Map<String,dynamic>> doc}) { uid = doc.id; // doc.id不会为null email = doc.data()?['email'] ?? ''; // 空值替换为默认值 accountCreated = doc.data()?['accountCreated']; fullName = doc.data()?['fullName'] ?? ''; groupId = doc.data()?['groupId']; notifToken = doc.data()?['notifToken']; }
内容的提问来源于stack exchange,提问作者Nizeyimana Jc
相关产品推荐
相关产品推荐

