Как эффективно получить доступ к данным эталонного поля пожарного депо во флаттере? - PullRequest
0 голосов
/ 19 октября 2018

Используя код, похожий на пример флаттера , предположим, что в документе снимка хранится поле ссылки, называемое: document['userRef'].

Прежде всего, как получить доступ кданные userRef?Используя document['userRef'].get().data или document['userRef'].get().username, я не смог получить доступ к данным.(NoSuchMethodError: Class 'Future<DocumentSnapshot>' has no instance getter 'data')

Я также пытался использовать document['userRef'].get().then(...), но получал ошибку: type 'Future<dynamic>' is not a subtype of type 'String'

Даже если .then сработает, он не будет искать ту же ссылкуопять за каждое сообщение?Здесь база данных обновляется в режиме реального времени, но нет необходимости выполнять одинаковый поиск для нескольких сообщений в ListView.

class MessageList extends StatelessWidget {
  MessageList({this.firestore});

  final Firestore firestore;

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<QuerySnapshot>(
      stream: firestore.collection('messages').snapshots(),
      builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
        if (!snapshot.hasData) return const Text('Loading...');
        final int messageCount = snapshot.data.documents.length;
        return ListView.builder(
          itemCount: messageCount,
          itemBuilder: (_, int index) {
            final DocumentSnapshot document = snapshot.data.documents[index];
            // document['userRef'] exists here
            return ListTile(
              title: Text(document['message'] ?? '<No message retrieved>'),
              subtitle: Text('Message ${index + 1} of $messageCount'),
            );
          },
        );
      },
    );
  }
}

Редактировать: я смог получить вложенные данные с помощью FutureBuilder, хотя и не уверен, насколько эффективноэто.(Разве это не может посылать множество избыточных запросов в Firebase?)

Создание виджета для вложенных данных, где существует документ ['userRef']:

        FutureBuilder(
          future: userData(document['userRef']),
          builder: (BuildContext context,
              AsyncSnapshot<dynamic> uData) {
            return Text(uData.data['username']);
          },
        );

И userDataфункция выглядит так:

Future<dynamic> userData(DocumentReference user) async {
  DocumentSnapshot userRef = await user.get();
  return userRef.data;
}

1 Ответ

0 голосов
/ 24 октября 2018

Придерживаясь способов Firebase и Flutter, можно использовать Streambuilder внутри Streambuilder.То есть вместо использования FutureBuilder для вложенных данных, что заставляет вас ждать каждый запрос .get.

(код не проверен, но принцип проверен.)

class MessageList extends StatelessWidget {
  MessageList({this.firestore});

  final Firestore firestore;

  @override
  Widget build(BuildContext context) {
    Map UserSnapshot = Map(); // create a variable for accessing users by id

    return StreamBuilder<QuerySnapshot>(
        stream: firestore.collection('users').snapshots(),
        builder:
            (BuildContext context, AsyncSnapshot<QuerySnapshot> UsersSnapshot) {
          // process usersnapshot from list to map
          UsersSnapshot.data.documents.forEach((userRecord) {
            //print(optionRecord.documentID); // debug
            UserSnapshot[userRecord.documentID] = userRecord;
          });
          // user data can be accessed as soon as there is a reference field or documentID:
          // UserSnapshot[document['userRef']]['userName'}

          return StreamBuilder<QuerySnapshot>(
            stream: firestore.collection('messages').snapshots(),
            builder: (BuildContext context,
                AsyncSnapshot<QuerySnapshot> MessagesSnapshot) {
              if (!MessagesSnapshot.hasData) return const Text('Loading...');
              final int messageCount = MessagesSnapshot.data.documents.length;
              return ListView.builder(
                itemCount: messageCount,
                itemBuilder: (_, int index) {
                  final DocumentSnapshot document =
                      MessagesSnapshot.data.documents[index];
                  // document['userRef'] exists here
                  // UserSnapshot[document['userRef']]['userName'} is accessible here
                  return ListTile(
                    title:
                        Text(document['message'] ?? '<No message retrieved>'),
                    subtitle: Text('Message ${index + 1} of $messageCount'),
                  );
                },
              );
            },
          );
        });
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...