Search code examples
firebasefluttergoogle-cloud-firestorestream-builder

flutter: type '(DocumentSnapshot<MyObject>) => MyObject' is not a subtype of type '(DocumentSnapshot<Object>) => MyObject'


I have difficulties to read (and show) data from firebase DB. I get this warning: type '(DocumentSnapshot) => GivitUser' is not a subtype of type '(DocumentSnapshot) => GivitUser'

I realy don't know what I'm doing wrong, I tried to convert from DocumentSnapshot to DocumentSnapshot but without success. this is my database.dart file:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:givit_app/models/givit_user.dart';

class DatabaseService {
  final String uid;
  DatabaseService({@required this.uid});

  final CollectionReference userCollection =
      FirebaseFirestore.instance.collection('Users');

  Future<void> updateGivitUserData(
      String email, String fullName, String password, int phoneNumber) async {
    return await userCollection.doc(uid).set({
      'Email': email,
      'Full Name': fullName,
      'Password': password,
      'Phone Number': phoneNumber,
    });
  }

  Future<GivitUser> getGivitUser(String uid) async {
    return await userCollection.doc(uid).get().then((user) => user.data());
  }

  GivitUser _userDataFromSnapshot(DocumentSnapshot<GivitUser> snapshot) {
    return GivitUser(
      uid: uid,
      email: snapshot.data().email,
      fullName: snapshot.data().fullName,
      phoneNumber: snapshot.data().phoneNumber,
    );
  }

  Stream<GivitUser> get userData {
    return userCollection.doc(uid).snapshots().map(_userDataFromSnapshot);
  }
}

and this is where I try to use the database.dart file and present the data:

  Widget build(BuildContext context) {
    GivitUser user = Provider.of<GivitUser>(context);
    final DatabaseService db = DatabaseService(uid: user.uid);
    return StreamBuilder<GivitUser>(
        stream: db.userData,
        builder: (context, snapshot) {
          if (!snapshot.hasData) {
            return Loading();
          }
          print('after getter');
          print(snapshot.data);
          GivitUser givitUser = snapshot.data;
          return Scaffold(
          ....
          ....
          ....

Thank in advance, I will appreciate any help :)

edit: a screenshot of the error: ERROR SCREENSHOT


Solution

  • This line userCollection.doc(uid).snapshots() returns Stream<DocumentSnapshot> and not Stream<DocumentSnapshot<GivitUser>> as you declared in the _userDataFromSnapshot argument.

    Reference

    Stream<DocumentSnapshot> snapshots({bool includeMetadataChanges = false})

    You need to change this block of code below:

        GivitUser _userDataFromSnapshot(DocumentSnapshot<GivitUser> snapshot) {
            //...
          }
    

    to this:

        GivitUser _userDataFromSnapshot(DocumentSnapshot snapshot) {
           //...
          }
    

    snapshot.data() returns a Map<String, dynamic> object. So you can get your data like you would from a Map object.

    The _userDataFromSnapshot method can be updated to:

        GivitUser _userDataFromSnapshot(DocumentSnapshot snapshot) {
            var snapshotData = snapshot.data() as Map;
            return GivitUser(
               uid: uid,
               email: snapshotData['Email'],
               fullName: snapshotData['Full Name'],
               phoneNumber: snapshotData['Phone Number'],
            );
       }