Flutter: Items in StreamBuilder(Using firebase realtime database) are sorted randomly
When you call snap.data.snapshot.value;
the data in the snapshot (which is ordered) is converted to a Map<String, Object>
which isn't ordered. To maintain the order, you'll want to listen to onChild...
instead.
Note that FlutterFire has a convenient firebase_list
library that handles most of the heavy lifting of onChild...
for you.
Also see:
- Flutter Firebase Database wrong timestamp order
- Flutter sort Firebase snapshot by timestamp
- Flutter: Firebase Real-Time database orderByChild has no impact on query result
Wilson Wilson
Freelance Flutter developer. I occasionally dream in Dart.
Updated on December 19, 2022Comments
-
Wilson Wilson over 1 year
I'm creating a simple application with Firebase Realtime database where a user inputs a text and it gets added to a list of chats.
void main() => runApp(MyApp()); class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Demo', theme: ThemeData( primarySwatch: Colors.indigo, ), home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { var _firebaseRef = FirebaseDatabase().reference().child('chats'); TextEditingController _txtCtrl = TextEditingController(); @override Widget build(BuildContext context) { var comments = _firebaseRef.orderByChild('time').limitToLast(10); return Scaffold( body: Container( child: SafeArea( child: Column( children: <Widget>[ Container( child: Row(children: <Widget>[ Expanded(child: TextField(controller: _txtCtrl)), SizedBox( width: 80, child: OutlineButton( child: Text("Add"), onPressed: () { sendMessage(); })) ])), StreamBuilder( stream: comments.onValue, builder: (context, snap) { if (snap.hasData && !snap.hasError && snap.data.snapshot.value != null) { Map data = snap.data.snapshot.value; List item = []; data.forEach( (index, data) => item.add({"key": index, ...data})); return Expanded( child: ListView.builder( itemCount: item.length, itemBuilder: (context, index) { return ListTile( title: Text(item[index]['message']), ); }, ), ); } else return Center(child: Text("No data")); }, ), ], ), ), ), ); } sendMessage() { _firebaseRef.push().set({ "message": _txtCtrl.text, 'time': DateTime.now().millisecondsSinceEpoch }); } }
It stores and retrieves data perfectly. But when I try adding data, the new items are placed at random points in the list.
For example, in the image below, the last item I placed into the list was 'Nine'. But it was put in the center of the list:
I've tried sorting the list by timestamps, but it did nothing.
What could be causing this issue? And how can I fix it?