Как получить список, используя дочернее событие firebase в флаттере?
Я хочу получить список из моей базы данных Firebase в реальном времени, используя дочерний метод firebase с использованием объекта Stream. Я настроил свое приложение следующим образом, но я получаю только 1 "вопрос" (самый новый), который загружается, а остальное не загружается вообще.
У меня есть более 5 вопросов в моей базе данных. Как я могу получить список из 5 новейших вопросов из моей базы данных в реальном времени?
class _QuestionPageState extends State<QuestionsPage> {
List _questions = [];
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
body: new StreamBuilder(
stream: FirebaseDatabase.instance
.reference()
.child('questions')
.limitToLast(5)
.onChildAdded,
builder: (context, snap) {
if (snap.hasError) return new Text('Error: ${snap.error}');
if (snap.data == null)
return new Center(
child: new CircularProgressIndicator(),
);
print(snap.data.snapshot.key);
print(snap.data.snapshot);
final question = snap.data.snapshot.value;
this._questions.add(question);
return new ListView.builder(
itemCount: this._questions.length,
itemBuilder: (context, index) {
print("question");
print(this._questions[index]["meta"]["question"]);
return new Text(this._questions[index]["meta"]["question"]);
},
);
},
),
);
}
}
[Обновлено] Это структура базы данных
1 ответ
Я также столкнулся с этой проблемой и обнаружил, что проще НЕ использовать виджет StreamBuilder. При использовании StreamBuilder мне пришлось использовать.onValue вместо.onChildAdded, чтобы вернуть все дочерние элементы, но.onValue вернул дочерние элементы в непредсказуемом порядке, потому что он возвращался как карта.
Вместо этого я думаю, что лучше всего создать StreamSubscription и вызвать ее в initState(), как показано ниже. Новые дочерние элементы добавляются в массив, а массив используется для построения ListView. Я вставляю новых дочерних элементов с индексом 0, чтобы новейшие записи находились в верхней части таблицы.
class NotificationsFeedPage extends StatefulWidget {
@override
_NotificationsFeedPageState createState() => _NotificationsFeedPageState();
}
class _NotificationsFeedPageState extends State<NotificationsFeedPage> {
List <Notification> notificationList = [];
StreamSubscription <Event> updates;
@override
void initState() {
// TODO: implement initState
super.initState();
updates = FirebaseDatabase.instance.reference().child('notifications').child(currentUser.uid).limitToLast(50).onChildAdded.listen((data) {
notificationList.insert(0, Notification.fromFireBase(data.snapshot));
setState(() {
});
} );
}
@override
void dispose() {
// TODO: implement dispose
updates.cancel();
super.dispose();
}
Где уведомление это пользовательский класс следующим образом:
class Notification {
String name;
bool isComment;
String user;
String comment;
Notification.fromFireBase(DataSnapshot snapshot) {
this.name = snapshot.value["name"] ?? 'Unknown user';
this.isComment = snapshot.value["isComment"] ?? false;
this.user = snapshot.value["user"] ?? '';
this.comment = snapshot.value["comment"] ?? '';
}
}
Это продолжает слушать, пока представление не расположено. Прослушивание прекращается при вызове updates.cancel().
Попробуйте не использовать "onChildAdded". Это только получает последний добавленный ребенок. Вы хотите всех детей, но хотите ограничить себя 5 самыми последними (что вы делаете с помощью limitToLast).