Flutter从Firebase读取数据时List<dynamic>转List<double>类型错误
Firestore映射用户文档时List转List类型错误
从Firebase Firestore读取用户文档并映射到AppUser模型时,遭遇类型转换错误:type 'List<dynamic>' is not a subtype of type 'List<double>'。Firestore返回的列表默认是List<dynamic>类型,无法直接赋值给模型中定义的List<double>字段,同时代码中存在字段名拼写错误,进一步引发问题。
出错方法代码
void appUser() async { final String id = await PathUtils().readID(); DocumentReference documentReference = FirebaseFirestore.instance.collection('users').doc(id.toString()); documentReference.get().then( (DocumentSnapshot documentSnapshot) { final data = documentSnapshot.data() as Map<String, dynamic>; print(data); //final userValues = data.values.toList(); final AppUser user = AppUser( email: data['email'], userName: data['userName'], listaSchede: data['listaSchede'], latestWorkouts: data['latestWorkouts'], volumeTot: data['volumeTot'], volumeSettimanale: data['volumeSettimanale'], listaPesi: data['listaPesi'], pesoAttuale: data['pesoAttuale'], altezza: data['altezza'], age: data['età'], circBicipiti: data['circBicipiti'], listaCircBicipiti: data['listaCircBicipiti'], circTricipiti: data['circTricipiti'], listaCircTricipiti: data['listaCircTricipit'], // 字段名拼写错误 circVita: data['circVita'], listaCircVita: data['listaCircVita'], id: data['id'], createdAt: data['createdAt'], ); print(user.toMap()); state = user; }, onError: (e) { print('error: $e'); }, ); }
AppUser模型代码
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:gym/models/scheda_model.dart'; import 'package:gym/models/workout_model.dart'; import 'package:uuid/uuid.dart'; const Uuid uuid = Uuid(); class AppUser { AppUser( {required this.email, required this.userName, required this.listaSchede, required this.latestWorkouts, required this.volumeTot, required this.volumeSettimanale, required this.listaPesi, required this.pesoAttuale, required this.altezza, required this.age, required this.circBicipiti, required this.listaCircBicipiti, required this.circTricipiti, required this.listaCircTricipiti, required this.circVita, required this.listaCircVita, required this.id, required this.createdAt}); factory AppUser.createNewUser({ required String? email, required String password, required String userName, String? id, }) { return AppUser( id: id ?? uuid.v4(), email: email, userName: userName, listaSchede: [], latestWorkouts: [], volumeTot: 0.0, volumeSettimanale: [], listaPesi: [], pesoAttuale: 0.0, altezza: 0.0, age: 0, circBicipiti: 0, listaCircBicipiti: [], circTricipiti: 0, listaCircTricipiti: [], circVita: 0, listaCircVita: [], createdAt: FieldValue.serverTimestamp(), ); } final String? email; final String userName; final String id; final List<Scheda> listaSchede; // 自定义模型 final double volumeTot; final List<double> volumeSettimanale; final List<Workout> latestWorkouts; // 自定义模型 final List<double> listaPesi; final double pesoAttuale; final double altezza; final int age; final double circBicipiti; final List<double> listaCircBicipiti; final double circTricipiti; final List<double> listaCircTricipiti; final double circVita; final List<double> listaCircVita; final FieldValue createdAt; Map<String, dynamic> toMap() { return { 'id': id, 'email': email, 'userName': userName, 'listaSchede': listaSchede, 'latestWorkouts': latestWorkouts, 'volumeTot': volumeTot, 'volumeSettimanale': volumeSettimanale, 'listaPesi': listaPesi, 'pesoAttuale': pesoAttuale, 'altezza': altezza, 'age': age, 'circBicipiti': circBicipiti, 'listaCircBicipiti': listaCircBicipiti, 'circTricipiti': circTricipiti, 'listaCircTricpiti': listaCircTricipiti, 'circVita': circVita, 'listaCircVita': listaCircVita, 'createdAt': createdAt, }; } }
完整错误信息
[VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'List<double>' #0 UserState.appUser.<anonymous closure> user_provider.dart:52 <asynchronous suspension> #1 UserState.appUser.<anonymous closure> user_provider.dart:42 <asynchronous suspension>
数据打印示例
{id: hzQAvGSdFOab8VwewJSWhCGiTpu1, listaPesi: [], pesoAttuale: 4.0, age: 232, circBicipiti: 0.0, latestWorkouts: [], circTricipiti: 0.0, altezza: 43.0, listaSchede: [], userName: asdgdsf, volumeSettimanale: [], circVita: 0.0, listaCircVita: [], volumeTot: 0.0, listaCircTricpiti: [], email: sdgsdg@mfds.com, createdAt: Timestamp(seconds=1692893432, nanoseconds=646000000), listaCircBicipiti: []}
解决方案
1. 修复字段名拼写错误
映射代码中listaCircTricipiti对应的Firestore字段是listaCircTricpiti,需将data['listaCircTricipit']改为data['listaCircTricpiti'],确保和Firestore中的键名一致。
2. 显式转换List为List
对每个List<double>类型的字段,将Firestore返回的动态列表通过map转换为指定类型:
// 示例转换写法 volumeSettimanale: (data['volumeSettimanale'] as List).map((e) => e as double).toList(), listaPesi: (data['listaPesi'] as List).map((e) => e as double).toList(), listaCircBicipiti: (data['listaCircBicipiti'] as List).map((e) => e as double).toList(), listaCircTricipiti: (data['listaCircTricpiti'] as List).map((e) => e as double).toList(), listaCircVita: (data['listaCircVita'] as List).map((e) => e as double).toList(),
3. 添加fromMap工厂构造函数(推荐)
在AppUser模型中添加fromMap方法,统一处理类型转换和字段映射,避免重复代码:
factory AppUser.fromMap(Map<String, dynamic> data) { return AppUser( email: data['email'], userName: data['userName'], listaSchede: (data['listaSchede'] as List).map((e) => Scheda.fromMap(e as Map<String, dynamic>)).toList(), latestWorkouts: (data['latestWorkouts'] as List).map((e) => Workout.fromMap(e as Map<String, dynamic>)).toList(), volumeTot: data['volumeTot'] as double, volumeSettimanale: (data['volumeSettimanale'] as List).map((e) => e as double).toList(), listaPesi: (data['listaPesi'] as List).map((e) => e as double).toList(), pesoAttuale: data['pesoAttuale'] as double, altezza: data['altezza'] as double, age: data['age'] as int, circBicipiti: data['circBicipiti'] as double, listaCircBicipiti: (data['listaCircBicipiti'] as List).map((e) => e as double).toList(), circTricipiti: data['circTricipiti'] as double, listaCircTricipiti: (data['listaCircTricpiti'] as List).map((e) => e as double).toList(), circVita: data['circVita'] as double, listaCircVita: (data['listaCircVita'] as List).map((e) => e as double).toList(), id: data['id'], createdAt: data['createdAt'] as FieldValue, ); }
注意:需确保
Scheda和Workout模型也实现fromMap方法,用于转换自定义对象列表。
修改后的appUser方法
使用fromMap简化映射逻辑:
void appUser() async { final String id = await PathUtils().readID(); DocumentReference documentReference = FirebaseFirestore.instance.collection('users').doc(id.toString()); try { final DocumentSnapshot documentSnapshot = await documentReference.get(); final data = documentSnapshot.data() as Map<String, dynamic>; print(data); final AppUser user = AppUser.fromMap(data); print(user.toMap()); state = user; } catch (e) { print('error: $e'); } }
内容的提问来源于stack exchange,提问作者Francesco Zanoncelli
相关产品推荐
相关产品推荐

