#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. если вы можете связать пример кода, тогда будет полезно посмотреть, что происходит не так и где