【问题标题】:'docs' isn't defined for the type 'object'没有为“对象”类型定义“文档”
【发布时间】:2021-09-20 03:18:44
【问题描述】:

当我输入此代码时:

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' can't be unconditionally access because the reciever can be null”错误,但添加一个空检查解决了它。

这是其余代码以及其他相关部分

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'],
);}}

【问题讨论】:

  • 请完整提供与 Firestore 查询相关的 searchResultsFuture 声明

标签: flutter dart google-cloud-firestore


【解决方案1】:

我认为您需要查看更多 firebase 示例并检查使用的函数、返回类型和对象。

我会尽量简要介绍您可以做出的更改:

使用FutureBuilder(或StreamBuilder)很好。更好的是使用dart generics

例如FutureBuilder&lt;User&gt;(...)

在执行 Firestore 查询时,您必须清楚自己得到了什么。你收到的是QuerySnapshot 还是DocumentSnapshot

使用QuerySnapshot,您将从查询的Firestore collection 中获得一堆Documents,您可以在其中获得Stream.snapshots() (example) 或使用@ 获取最新的987654335@(example)。

这样做会给你一个QuerySnapshot&lt;Map&lt;String, dynamic&gt;&gt;,它有一个docs getter,你可以.map()这个到另一种类型或你选择的对象(参见example),你可以在@中使用它987654339@ 或稍后对其进行处理。


以你的例子,我会建议类似的东西:

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;
  //...

最后,使用FutureBuilder&lt;List&lt;User&gt;&gt; 来检索您的数据并显示它,例如(未经测试)

@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
    ),
  );
}

【讨论】:

    猜你喜欢
    • 2021-08-22
    • 2022-01-25
    • 1970-01-01
    • 2021-11-16
    • 2020-10-08
    • 2021-08-28
    • 2021-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多