flutter - 没有为“对象”类型定义“文档”
问题描述
当我输入此代码时:
buildSearchRes() {
return FutureBuilder(
future: searchResultsFuture,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return cargandoCircular();
}
List<UserRes> searchRes = [];
snapshot.data!.docs.forEach((doc) {
User user = User.fromDocument(doc);
UserRes searchRes = UserRes(user);
searchRes.add(searchRes);
});
return ListView(
children: searchRes,
);
},
);
}
我得到错误:
The getter 'docs' isn't defined for the type 'Object'.
Try importing the library that defines 'docs', correcting the name to the name of an existing getter, or defining a getter or field named 'docs'.
我已经在导入cloud_firestore
包了。
我曾经得到一个“'docs'不能无条件访问,因为接收者可以为空”错误,但添加一个空检查解决了它。
这是代码的其余部分以及其他相关部分
class _BuscarPerfilState extends State<BuscarPerfil> {
TextEditingController searchController = TextEditingController();
late Future<QuerySnapshot>? searchResultsFuture;
handleSearch(String query) {
Future<QuerySnapshot> users = usersRef
.where("displayName", isGreaterThanOrEqualTo: query)
.get(); //getDocuments();
setState(() {
searchResultsFuture = users;
});}
AppBar buildSearchField() {
return AppBar(
backgroundColor: Colors.white,
title: TextFormField(
controller: searchController,
decoration: InputDecoration(
hintText: "Buscar un usuario...",
filled: true,
prefixIcon: Icon(
Icons.account_box,
size: 28.0,
),
suffixIcon: IconButton(
icon: Icon(Icons.clear),
onPressed: clearSearch,
),
),
onFieldSubmitted: handleSearch,
),
);}
buildSearchResults() {
return FutureBuilder(
future: searchResultsFuture,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return cargandoCircular();
}
List<UserResult> searchResults = [];
snapshot.data!.docs.forEach((doc) {
User user = User.fromDocument(doc);
UserResult searchResult = UserResult(user);
searchResults.add(searchResult);
});
return ListView(
children: searchResults,
);
},
);}
@override
Widget build(context) {
return Scaffold(
backgroundColor: Theme.of(context).primaryColor.withOpacity(0.2),
appBar: buildSearchField(),
body:
searchResultsFuture == null ? buildNoContent() : buildSearchResults(),
);}}
为了对用户数据进行建模,我在另一个 .dart 文档上做了这个并导入了它:
class User {
final String id;
final String username;
final String email;
final String photoUrl;
final String displayName;
final String bio;
User(
{required this.id,
required this.username,
required this.email,
required this.photoUrl,
required this.displayName,
required this.bio});
factory User.fromDocument(DocumentSnapshot doc) {
return User(
id: doc['id'],
email: doc['email'],
username: doc['username'],
photoUrl: doc['photoUrl'],
displayName: doc['displayName'],
bio: doc['bio'],
);}}
解决方案
我认为您需要查看更多 firebase 示例并检查使用的函数、返回类型和对象。
我将尝试简要介绍您可以进行的更改:
使用FutureBuilder(或StreamBuilder)很好。更好的是使用dart 泛型。
例如FutureBuilder<User>(...)
执行 Firestore 查询时,您必须知道您得到了什么。你得到的是QuerySnapshot还是DocumentSnapshot。
使用 a ,您将从查询的 Firestore集合QuerySnapshot
中获得一堆文档,您可以在其中获取 a of ( example ) 或获取最新的 using ( example )。Stream
.snapshots()
.get()
这样做会为您提供QuerySnapshot<Map<String, dynamic>>
具有docs
吸气剂的 a,您可以.map()
将其用于另一种类型或您选择的对象(参见示例),您将在 a 中使用它ListView
或稍后对其进行处理。
以你的例子,我会建议类似的东西:
class FirestoreService {
final FirebaseFirestore _firebaseFirestore = FirebaseFirestore.instance;
Future<List<User>> searchUsersByDisplayName(String displayName) {
const usersRef = _firebaseFirestore.collections(...);
return usersRef.where("displayName", isGreaterThanOrEqualTo: query).get().then((value) => value.docs.map(User.fromDocument).toList());
}
}
将您的查询与您的视图分开,否则它会变得混乱,并且您会遇到一堆问题。
接下来,您的小部件状态,使用后期或空安全,而不是两者:
class _BuscarPerfilState extends State<BuscarPerfil> {
TextEditingController searchController = TextEditingController();
Future<List<User>>? searchResultsFuture;
//...
最后,用户 aFutureBuilder<List<User>>
检索您的数据并显示它,例如(未经测试)
@override
Widget build(context) {
FirestoreService _firestoreService = FirestoreService();
return Scaffold(
backgroundColor: Theme
.of(context)
.primaryColor
.withOpacity(0.2),
appBar: buildSearchField(),
body: FutureBuilder<List<User>>( // user futurebuilder or streambuilder
builder: (context, snapshot) {
// always check for errors
if (!snapshot.hasError) {
return Text("Error retrieving results");
}
// depending on the connection state, you want to show different UI updates
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
// we are waiting on a connection, etc
return CircularProgressIndicator();
case ConnectionState.active:
case ConnectionState.done:
// we are grabbing data, this *can* continue on for a few seconds or we are done
// display results as you wish
return ListView.separated(
itemBuilder: (context, index) {
User user = snapshot.data[index];
return ListTile(
title: Text(user.displayName),
leading: CircleAvatar(
foregroundImage: Image
.network(user.photoUrl)
.image,
),
subtitle: Text(user.email),
onTap: () {
// go to profile page
},
)
},
separatorBuilder: (context, index) => Divider(),
itemCount: snapshot.data.length);
}
},
future: _firestoreService
.searchUsersByDisplayName("query value here") // your Future query
initialData: [], // empty data to begin with
),
);
}
推荐阅读
- java - JPA 多对多抛出 PropertyReferenceException
- javascript - 在javascript和firebase中使用“createUserWithEmailAndPassword(email,password)”时如何获取用户ID
- javascript - 隐藏引导模式时出错
- sas - SAS:在批处理模式下运行时切换 DM 命令
- c# - C# 从 SQL 数据库返回所有表信息
- azure - 将 Sql 数据库项目部署到 Azure,但应用程序失败
- angular - Angular无法读取未定义的属性“订阅”
- java - 从 ArrayList 获取编辑的 JTextField
- pdf - 是否需要在要由多个用户签名的 PDF 上添加空签名外观
- javascript - 使用 fetch API 通过 post 请求传递 json 数据并在 express 后端获取