Home > Net >  StreamBuilder data with two Emulators
StreamBuilder data with two Emulators

Time:05-11

I am experiencing weird(to my knowledge) behaviour of StreamListener data when I turn on two emulators.

I have a block of code to read Firebase's RealtimeDB and return it in ListView.

body: StreamBuilder(
    stream: _database.onValue,
    builder: (context, snapshot) {
      List<FirstRoundQuestion> frqList = [];
      if (snapshot.hasData) {
        final firstRoundQuestion = Map<dynamic, dynamic>.from(
            (snapshot.data! as DatabaseEvent).snapshot.value
                as Map<dynamic, dynamic>);
        firstRoundQuestion.forEach((key, value) {
          final frq = Map<String, dynamic>.from(value);
          frqList.add(FirstRoundQuestion(
              question: frq['question'],
              answer: frq['answer'],
              answered: frq['answered']));
        });
        return ListView.builder(
          reverse: true,
          physics: NeverScrollableScrollPhysics(),
          controller: _controller.pageController,
          itemCount: frqList.length,
          itemBuilder: (context, index) {
            return Row(
              children: [
                Text('${frqList[index].question}'),
                TextButton(
                    onPressed: ()  {}
                          
                    child: Text('${frqList[index].answered}'))
              ],
            );
          },
        );
      } else {
        return Text("Doesn't work");
      }
    }));

What I get when buiild app on mobile simulator and then edge simulator is two different orders of this list, first one is ascending and the other one is descending. What am I missing here guys? :o

Hopefully I explained understandably.

CodePudding user response:

To show the items in a specific order, you need to do two things:

  1. Retrieve the items in that order from the database.
  2. Then process them in the order you received them in your code.

If you're not requesting the items in a specific order from the database yet, you can for example do:

body: StreamBuilder(
  stream: _database.orderByKey().onValue,
  ...

Once you requests the item in a certain order, it's this code in your builder that fails to process the items in order:

if (snapshot.hasData) {
  final firstRoundQuestion = Map<dynamic, dynamic>.from(
      (snapshot.data! as DatabaseEvent).snapshot.value
          as Map<dynamic, dynamic>);
  firstRoundQuestion.forEach((key, value) {
    final frq = Map<String, dynamic>.from(value);
    frqList.add(FirstRoundQuestion(
        question: frq['question'],
        answer: frq['answer'],
        answered: frq['answered']));
  });

The order of the items in a map is undefined, so when you convert the entire value of the snapshot to a map, you are losing the order of the items.

The solution to processing the items in order is to loop over the children property of the snapshot:

(snapshot.data! as DatabaseEvent).snapshot.children.forEach((snapshot) {
  final frq = Map<Sting, dynamic>.from(snapshot.value as Map<dynamic, dynamic>);
  frqList.add(FirstRoundQuestion(
      question: frq['question'],
      answer: frq['answer'],
      answered: frq['answered']));
})
  • Related