Как получить список, используя дочернее событие 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).

Другие вопросы по тегам