Почему в этом случае я получаю ошибку плохого состояния?

# #firebase #flutter #google-cloud-firestore

Вопрос:

Я обновил все свои пакеты до последней версии, и теперь я получаю эту ошибку: Bad state: field does not exist within the DocumentSnapshotPlatform при извлечении некоторых данных.

Я нашел здесь некоторые проблемы, связанные с той же проблемой, но ни одна из них не решила мою проблему, большинство из них были связаны с изменениями в том, как работает DocumentSnapshot, и я, вероятно, пропустил что-то из документации, что вызывает эту ошибку.

Что ж, я опишу ниже, в чем, по-моему, проблема, и полный код.

Я думаю, что проблема здесь

 List<UserResult> searchResults = [];
 snapshot.data.docs.forEach((doc) {
  Users user = Users.fromDocument(doc);
  UserResult searchResult = UserResult(user);
  searchResults.add(searchResult);
});
 

Вещи, которые я пробовал, и это не сработало

1:

 List<UserResult> searchResults = [];
  snapshot.data().docs.forEach((doc) {
  Users user = Users.fromDocument(doc);
  UserResult searchResult = UserResult(user);
  searchResults.add(searchResult);
 });
 

2:

 List<UserResult> searchResults = [];
  var item = snapshot.data();
   item.docs.forEach((doc) {
   Users user = Users.fromDocument(doc);
   UserResult searchResult = UserResult(user);
   searchResults.add(searchResult);
 });
 

Для понимания

 class _SearchState extends State<Search> {
  TextEditingController searchController = TextEditingController();
  Future<QuerySnapshot> searchResultsFuture;

  handleSearch(String query) {
      Future<QuerySnapshot> results =
          usersRef.where("tag", isEqualTo: query).get();

      setState(() {
        searchResultsFuture = results;
      });
  }

  buildResults() {
    return FutureBuilder(
      future: searchResultsFuture,
      builder: (context, snapshot) {
        if (snapshot.connectionState != ConnectionState.done) {
          return SizedBox(
              child: CircularProgressIndicator(),
            );
        }
        List<UserResult> searchResults = [];
        snapshot.data.docs.forEach((doc) {
          Users user = Users.fromDocument(doc);
          UserResult searchResult = UserResult(user);

          searchResults.add(searchResult);
        });
        return SingleChildScrollView(
          child: Column(
            children: searchResults,
          ),
        );
      },
    );
  }

  buildNoContent() {
    return Container();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Container(
            child: SingleChildScrollView(
              child: Column(
                children: <Widget>[
                  Center(
                    child: Text(
                        "Type something",
                      ),
                    ),
                  TextFormField(
                    enableInteractiveSelection: true,
                    controller: searchController,
                    keyboardType: TextInputType.text,
                    onFieldSubmitted: handleSearch(searchController.text),
                  ),
                  
                  searchResultsFuture == null
                      ? buildNoContent()
                      : buildResults(),
                ],
              ),
            ),
      ),
    );
  }
}
 

Метод fromDocument

 import 'package:cloud_firestore/cloud_firestore.dart';

class Users {
  String id;
  String email;
  String tag;

  Users(
      {this.id,
      this.email,
      this.tag});

  factory Users.fromDocument(DocumentSnapshot doc) {
    return Users(
        id: doc.id,
        email: doc['email'],
        tag: doc['tag']);
  }
}
 

Ответ №1:

Изменить

 FutureBuilder(
 

Для

 FutureBuilder<QuerySnapshot>(

 

И в вашем заводском методе сделайте это:

 factory Users.fromDocument(DocumentSnapshot doc) {
    return Users(
        id: doc.id,
        email: doc.data()['email'],
        tag: doc.data()['tag']);
  }
 

Комментарии:

1. Ошибка после этого: The following _TypeError was thrown building FutureBuilder<QuerySnapshot<Object>>(dirty, state: _FutureBuilderState<QuerySnapshot<Object>>#3b666): type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'DocumentSnapshot<Object>'

2. Это другая ошибка, поделитесь своим fromDocument методом, пожалуйста.

3. Я сделал именно то, что вы предлагаете: Users user = Users.fromDocument(doc.data());

4. Это также появляется: When the exception was thrown, this was the stack: #0 _SearchState.buildResults.<anonymous closure>.<anonymous closure> (package:flutter/screens/search.dart:67:47) #1 List.forEach (dart:core-patch/growable_array.dart:403:8) #2 _SearchState.buildResults.<anonymous closure>

5. можете ли вы поделиться своим fromDocument методом? Ошибка происходит оттуда.

Ответ №2:

После перепробования тонны комбинаций это сработало:

Метод fromDocument

 import 'package:cloud_firestore/cloud_firestore.dart';

class Users {
  String id;
  String email;
  String tag;

  Users(
      {this.id,
      this.email,
      this.tag});

  factory Users.fromDocument(DocumentSnapshot<Map<String, dynamic>> doc) {
    return Users(
        id: doc.id,
        email: doc.data()['email'],
        tag: doc.data()['tag']);
  }
}
 

Будущий строитель

 class _SearchState extends State<Search> {
  TextEditingController searchController = TextEditingController();
  Future<QuerySnapshot<Map<String, dynamic>>> searchResultsFuture;

  handleSearch(String query) {
      Future<QuerySnapshot> results =
          usersRef.where("tag", isEqualTo: query).get();

      setState(() {
        searchResultsFuture = results;
      });
  }

  buildResults() {
    return FutureBuilder<QuerySnapshot<Map<String, dynamic>>>(
      future: searchResultsFuture,
      builder: (context, snapshot) {
        if (snapshot.connectionState != ConnectionState.done) {
          return SizedBox(
              child: CircularProgressIndicator(),
            );
        }
        List<UserResult> searchResults = [];
        snapshot.data.docs.forEach((doc) {
          Users user = Users.fromDocument(doc);
          UserResult searchResult = UserResult(user);

          searchResults.add(searchResult);
        });
        return SingleChildScrollView(
          child: Column(
            children: searchResults,
          ),
        );
      },
    );
  }
 

В основном я просто добавил <Карта<Строка, динамическая><Строка, динамическая>>