skip to Main Content

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: [email protected], createdAt: Timestamp(seconds=1692893432, nanoseconds=646000000), listaCircBicipiti: []}

5

Answers


  1. Chosen as BEST ANSWER

    I solved the issues in this way:

    • I add a .fromDataMap() method for Scheda and Workout (which is shown down there)
    • I edited the 'simplest' lists in a few lines of code form which you can extract a method (I'll do that another time)

    The method I added in Scheda and Workout models:

    factory Scheda.fromDataMap(Map<String, dynamic> data) {
        final List<dynamic> rawWorkoutList = data['workoutList'];
        final List<PersonalWorkout> workoutList = rawWorkoutList
            .map((workoutData) => workoutData as PersonalWorkout)
            .toList();
    
        return Scheda(
          id: data['id'],
          workoutList: workoutList,
          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
    

  2. it was showing that you are mentioning that the data that was coming inside list is double but it cant find simply change the list double to dynamic thankyou

    Login or Signup to reply.
  3. You have define data as List<double> but you receive List<dynamic> you must check

    volumeSettimanale
    listaPesi
    listaCircBicipiti
    listaCircTricipiti
    listaCircVita
    

    make sure your firestore data type matches your model data type.

    Login or Signup to reply.
  4. Don’t parse data hard coding use fromMap and always remember never typecast LIST

        return AppUser(
          email: map['email'] != null ? map['email'] as String : null,
          userName: map['userName'] as String,
          id: map['id'] as String,
          listaSchede: List<Scheda>.from(
            (map['listaSchede'] as List<int>).map<Scheda>(
              (x) => Scheda.fromMap(x as Map<String, dynamic>),
            ),
          ),
          volumeTot: map['volumeTot'] as double,
          volumeSettimanale: List<double>.from((map['volumeSettimanale'])),
          latestWorkouts: List<Workout>.from(
            (map['latestWorkouts'] as List<int>).map<Workout>(
              (x) => Workout.fromMap(x as Map<String, dynamic>),
            ),
          ),
          listaPesi: List<double>.from((map['listaPesi'])),
          pesoAttuale: map['pesoAttuale'] as double,
          altezza: map['altezza'] as double,
          age: map['age'] as int,
          circBicipiti: map['circBicipiti'] as double,
          listaCircBicipiti: List<double>.from((map['listaCircBicipiti'])),
          circTricipiti: map['circTricipiti'] as double,
          listaCircTricipiti: List<double>.from((map['listaCircTricipiti'])),
          circVita: map['circVita'] as double,
          listaCircVita: List<double>.from((map['listaCircVita'])),
        );
      }
    `
    
    Login or Signup to reply.
  5. The simplest way is to cast to double, something like this:

    data['volumeSettimanale'].cast<double>()
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search