I'm trying to map a document with different user data from a Firebase Firestore database. The error occurs when I try to cast values different from dynamic (lists in this case). Down there there is the part of code where I map the Firebase document and the user model. The method where the error occurs:
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');
},
);
}
user model:
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; //Scehda is another custom model
final double volumeTot;
final List<double> volumeSettimanale;
final List<Workout> latestWorkouts; //Workout is another custom model
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,
};
}
}
the full error:
[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>
Here is a sample of print(data):
{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: []}
I solved the issues in this way:
The method I added in Scheda and Workout models:
factory Scheda.fromDataMap(Map<String, dynamic> data) {
return Scheda(
id: data['id'],
workoutList: List<Workout>.from(
data['workoutList'].map((w) => Workout.fromDataMap(w))),
title: data['title'],
isActive: data['isActive'],
);
}
(for workout model)
factory Workout.fromDataMap(Map<String, dynamic> data) {
final List<dynamic> rawWorkoutList = data['workoutList'];
final List<PersonalExercise> workoutList = rawWorkoutList
.map((workoutData) => workoutData as PersonalExercise)
.toList();
if (data['duration'] == null) {
return Workout(
exerciseList: workoutList,
title: data['title'],
);
}
return Workout(
exerciseList: workoutList,
title: data['title'],
duration: data['duration'],
);
}
Finally, how I used that code:
final List<dynamic> rawSchedeList = data['listaSchede'];
final List<Scheda> schedeList = rawSchedeList
.map((schedaData) => Scheda.fromDataMap(schedaData))
.toList();
final List<dynamic> rawLatestWorkouts = data['latestWorkouts'];
final List<Workout> latestWorkouts = rawLatestWorkouts
.map((workData) => Workout.fromDataMap(workData))
.toList();
final List<dynamic> rawVolumeSet = data['volumeSettimanale'];
final List<double> volumeSet = rawVolumeSet
.map((volumeSingolo) => double.parse(volumeSingolo))
.toList(); //... and so on