Я не могу заставить Future завершиться со значением

Значение типа Object? не может быть возвращено из метода getUser, поскольку у него есть возвращаемый тип Future\<UserModel\>.

  Future<UserModel> getUser(String userId) async {
    QuerySnapshot userDoc = await _usersCollectionRef.where('userId', isEqualTo: userId).get();
    print('user doc: ${userDoc.docs[0].data()}'); //user doc: Instance of 'UserModel'
    return userDoc.docs[0].data();
  }

Почему будущее не завершится, хотя внутри явно есть UserModel возвращение.

РЕДАКТИРОВАТЬ Спасибо всем за ответы. Вот код или _usersCollectionRef

  FirestoreDatabase() {
_folderCollectionRef = _firestore.collection(FOLDERS_COLLECTON_REF).withConverter<FolderModel>(
    fromFirestore: (snapshots, _) => FolderModel.fromJson(
      snapshots.data()!,
    ),
    toFirestore: (folderModel, _) => folderModel.toJson());

_usersCollectionRef = _firestore.collection(USERS_COLLECTION_REF).withConverter<UserModel>(
    fromFirestore: (snapshots, _) => UserModel.fromJson(
      snapshots.data()!,
    ),
    toFirestore: (userModel, _) => userModel.toJson());}

Также вот код fromJson в моей UserModel:

UserModel.fromJson(Map<String, Object?> json)
  : this(
nickName: json['nickName']! as String,
userId: json['userId']! as String,
email: json['email']! as String,
role: json['role']! as String);

РЕДАКТИРОВАТЬ Кажется, я решил проблему. Я не знаю, хорошее ли это решение, но я все равно был бы признателен за отзывы о том, что было не так, в первую очередь, ради обучения:)

  Future<UserModel> getUser(String userId) async {
QuerySnapshot userDoc = await _usersCollectionRef.where('userId', isEqualTo: userId).get();
return userDoc.docs[0].data() as UserModel;}

51
2

Ответы:

QuerySnapshot — это универсальный класс QuerySnapshot<T extends Object?>.

В объявлении userDoc вы опустили параметр типа:

QuerySnapshot userDoc = await _usersCollectionRef.where(
  'userId', isEqualTo: userId,
).get();

Вот почему T по умолчанию имеет значение Object?, а userDoc.docs[0].data() предполагается, что он возвращает объект типа T. Анализатор не знает, что тип выполнения userDoc.docs[0].data() будет UserModel.


Пример с правильными параметрами типа:

import 'package:cloud_firestore/cloud_firestore.dart';

class UserModel {
  UserModel({required this.name, required this.id});
  final String name;
  final int id;

  factory UserModel.fromJson(Map<String, Object?> json) {
    if (json case {'name': String name, 'id': int id}) {
      return UserModel(name: name, id: id);
    } else {
      throw UnsupportedError('Could not convert $json to UserModel.');
    }
  }

  Map<String, Object?> toJson() => {'name': name};
}

// usersRef is and instance of CollectionReference<UserModel>
final usersRef = FirebaseFirestore.instance
    .collection('Sample_Path_User_Model')
    .withConverter<UserModel>(
      fromFirestore: (snapshots, _) => UserModel.fromJson(snapshots.data()!),
      toFirestore: (movie, _) => movie.toJson(),
    );

Future<UserModel> getUser(String userId) async {
  QuerySnapshot<UserModel> userDoc =
      await usersRef.where('userId', isEqualTo: userId).get();

  return userDoc.docs[0].data();
}


Решено

Ваш объект userDoc — это объект типа QuerySnapshot . Когда вы вызываете .docs[0], возвращается тип объекта QueryDocumentSnapshot . При дальнейшем вызове data() возвращается тип объекта T, который является объектом универсального типа. Итак, это не экземпляр UserModel, а карта, содержащая пары ключ-значение.

Если вы хотите преобразовать эти данные в объект класса UserModel, вам необходимо создать метод функции fromMap(), как описано в ответе из следующего сообщения: