Значение типа 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;}
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<UserModel>
и проверить, что при создании CollectionReference
использовался тот же параметр типа.
Когда я это делаю, я получаю сообщение об ошибке: значение типа «QuerySnapshot<Object?>» не может быть присвоено переменной типа «QuerySnapshot<UserModel>».
Ваш объект userDoc
— это объект типа QuerySnapshot . Когда вы вызываете .docs[0]
, возвращается тип объекта QueryDocumentSnapshot . При дальнейшем вызове data() возвращается тип объекта T
, который является объектом универсального типа. Итак, это не экземпляр UserModel
, а карта, содержащая пары ключ-значение.
Если вы хотите преобразовать эти данные в объект класса UserModel
, вам необходимо создать метод функции fromMap()
, как описано в ответе из следующего сообщения:
Спасибо за отличное объяснение, все логично. Но у меня уже есть функция fromJson() (я поставил ее в конце вопроса). Когда я попытался добавить функцию fromMap(), возникла та же проблема.
Что произойдет, если вы преобразуете userDoc.docs[0].data()
в объект типа UserModel
?
Я думаю, что последний бит, который я отредактировал, делает это, и это решает проблему, но я все еще не понимаю, что было не так в первую очередь.
Я собирался написать вам просто для того, чтобы превратить userDoc.docs[0].data()
в UserModel
. Я рад, что вы отредактировали свой вопрос. Я также отредактировал свой ответ.
Помог ли мой ответ/комментарий? Могу ли я помочь вам с другой информацией?
Да, большое спасибо. Я бы проголосовал за это, но у меня нет репутации :)
Пожалуйста, добавьте объявление
_usersCollectionRef
в свой код. Возможно, отсутствует параметр типа.