В базе данных Firebase в реальном времени и Flutter — Snapshot нет данных

#flutter #dart #firebase-realtime-database

#flutter #dart #firebase-realtime-database

Вопрос:

Я пытаюсь реализовать базу данных Firebase в реальном времени в Flutter, и я хочу отображать обновленные значения в режиме реального времени. Я пытаюсь добиться этого с StreamBuilder помощью .

Код StreamBuilder

 StreamBuilder(
  stream: GuestbooksDatabase().getAllGuestbooksSync().asStream(),
  builder: (context, snapshot) {
    if (!snapshot.hasData || !snapshot.data.length) {
      return CircularProgressIndicator();
    } else {
      return ListView.builder(
          shrinkWrap: true,
          itemCount: snapshot.data.length,
          itemBuilder: (context, index) {
            return Text(snapshot.data[index].title);
          });
    }
  }),
  

Функция потока

 Future<List<Guestbook>> getAllGuestbooksSync() async {
    List<Guestbook> guestbooks = [];
    databaseRef.onValue.listen((event) async {
      var dataSnapshot = event.snapshot;

      if (dataSnapshot.value != null) {
        dataSnapshot.value.forEach((key, value) async {
          Guestbook guestbook = await Guestbook.fromJson(value);
          guestbook.setId(key);
          guestbooks.add(guestbook);
        });

        await Future.delayed(Duration.zero);
        print(guestbooks); // Result: All Instances of Guestbook
        return guestbooks;
      }
    });
  }
  

Я вижу только CircularProgressIndicator() то, что означает, что в моментальном снимке нет данных.
В чем проблема?

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

1. что это значит!snapshot.data.length

2. Срабатывает, когда длина данных моментального снимка <= 0..

3. Вы уже проверили, какое из двух условий в snapshot.hasData || !snapshot.data.length true? Потому что последнее означает, что чтение завершено, но не привело к получению данных, в то время как первое означает, что чтение никогда не завершалось. Также: вы проверяли вывод приложения на наличие ошибок / предупреждений?

4. Если я print(snapshot.data) в StreamBuilder, результат будет null . Таким образом, данных нет, и !snapshot.hasData условие истинно.

5. PS: никаких ошибок, никаких предупреждений. Из getAllGuestbooksSync() я получаю правильный вывод, но StreamBuilder он этого не знает… :/

Ответ №1:

Вы можете использовать StreamController для этого.

Создайте новый контроллер —

 final StreamController streamController = StreamController<List>.broadcast();
  

Преобразуйте Future<List> в void type для вашей getAllGuestbooksSync() функции и ничего не возвращайте.

Он может и будет вызываться в initState()

 void getAllGuestbooksSync() {
    List<Guestbook> guestbooks = [];
    databaseRef.onValue.listen((event) async {
      var dataSnapshot = event.snapshot;

      if (dataSnapshot.value != null) {
        dataSnapshot.value.forEach((key, value) async {
          Guestbook guestbook = await Guestbook.fromJson(value);
          guestbook.setId(key);
          guestbooks.add(guestbook);
        });

        print(guestbooks); // Result: All Instances of Guestbook

        streamController.add(guestbooks); // Adding list to the stream
      }
    });
}
  

В вашем StreamBuilder использовании —

 stream: streamController.stream,
  

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

1. Это работает, если я использую функцию в том же файле, что и StreamBuilder, верно? Я использую getAllGuestbooksSync() в отдельном файле, который я использую в качестве службы базы данных. Это просто класс без виджета без состояния или виджета с отслеживанием состояния. Так что нет initState . Будет ли это также работать?

2. Вы можете использовать разные контроллеры в отдельных файлах, а затем передавать объект контроллера из одного класса в другой (из файла в другой). Так и должно работать.

3. Не работает. Журнал постоянно отображается flutter: AsyncSnapshot<dynamic>(ConnectionState.waiting, null, null)

4. если вы можете связать пример кода, тогда будет полезно посмотреть, что происходит не так и где