Flutterfire: [firestore] Different default order between web and mobile version.

Created on 19 Aug 2020  Â·  3Comments  Â·  Source: FirebaseExtended/flutterfire

Describe the bug
When I retrieve a document from Cloud Firestore, the default order of the snapshot keys is different.

To Reproduce
Steps to reproduce the behavior:

  1. Create a firestore document which contains maps in the root.
  2. Retrieve a document snapshot in flutter web and mobile (e.g. android)
  3. Get a list of the keys from the snapshot data (e.g. snapshot.data.keys.cast<String>().toList()).
  4. Generate a list of all maps with the order based on the key list you've retreived earlier.
  5. See that the order is different depending on behavior.

Expected behavior
I'd expect the default order to the be the same on all platforms.

Additional context
I have created a manual order system which sorts the list of keys based on specific criteria, instead of using the default order directly from Firebase. Just wanted to report this as I discovered it recently and because I would call different behavior for the same commands on different platforms a bug.

Flutter doctor

[√] Flutter (Channel beta, 1.20.2, on Microsoft Windows [Version 10.0.18363.1016], locale en-DE)

[√] Android toolchain - develop for Android devices (Android SDK version 30.0.0-rc2)
[√] Chrome - develop for the web
[√] Android Studio (version 4.0)
[√] IntelliJ IDEA Ultimate Edition (version 2019.2)
[√] VS Code (version 1.47.3)
[√] Connected device (3 available)

• No issues found!

EDIT : An example for this behavior - https://drive.google.com/file/d/1c2H3chI4uGYAI7QISd9yQvkCZmM1dOMX/view?usp=sharing

cloud_firestore invalid bug

Most helpful comment

Yep sorry much we can do about this - if data key order is important I'd suggest iterating the keys yourself.

All 3 comments

I ca reproduce the issue

Web

Screenshot 2020-08-19 at 4 27 29 PM

Mobile

Screenshot_1597834689

  firebase_core: ^0.5.0
  cloud_firestore: ^0.14.0


code sample

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  FirebaseApp app = await Firebase.initializeApp();
  assert(app != null);
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Material App',
      theme: ThemeData.dark(),
      home: Home(),
    );
  }
}

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Firestore Example'),
      ),
      body: Center(
        child: BookList(),
      ),
    );
  }
}

class BookList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<DocumentSnapshot>(
      stream: FirebaseFirestore.instance
          .collection('test_collection')
          .doc('6V13QoGJIYlGRc9K6G0I')
          .snapshots(),
      builder:
          (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
        if (snapshot.hasError) return new Text('Error: ${snapshot.error}');

        if (snapshot.hasData) {
          print(
              'keys ${snapshot.data.data().keys.cast<String>().toList().toString()}');

          return Container(
            child: Text(
                'keys ${snapshot.data.data().keys.cast<String>().toList().toString()}'),
          );
        }

        return Container();
      },
    );
  }
}


flutter doctor -v

[✓] Flutter (Channel dev, 1.21.0-9.0.pre, on Mac OS X 10.15.6 19G2021, locale
    en-GB)
    • Flutter version 1.21.0-9.0.pre at /Users/tahatesser/Code/flutter_dev
    • Framework revision 7c6f9dd239 (10 days ago), 2020-08-09 10:31:03 -0400
    • Engine revision 6d86e67f04
    • Dart version 2.10.0 (build 2.10.0-4.0.dev 0341576448)


[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
    • Android SDK at /Users/tahatesser/Code/sdk
    • Platform android-30, build-tools 30.0.1
    • ANDROID_HOME = /Users/tahatesser/Code/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 11.6)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 11.6, Build version 11E708
    • CocoaPods version 1.9.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.0)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 48.1.2
    • Dart plugin version 193.7361
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)

[✓] VS Code (version 1.48.0)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.13.2

[✓] Connected device (4 available)
    • Android SDK built for x86 (mobile) • emulator-5554 • android-x86    • Android 10 (API 29) (emulator)
    • macOS (desktop)                    • macos         • darwin-x64     • Mac OS X 10.15.6 19G2021
    • Web Server (web)                   • web-server    • web-javascript • Flutter Tools
    • Chrome (web)                       • chrome        • web-javascript • Google Chrome 84.0.4147.125

• No issues found!

I'm not sure this is one we can handle - Firestore doesn't provide any guarantee of key order (unlike RTDB) - only arrays are returned in expected order. Digging into it, the map returned is directly from a native call, and I wouldn't like to iterate a response in dart just incase it is huge.

Yep sorry much we can do about this - if data key order is important I'd suggest iterating the keys yourself.

Was this page helpful?
0 / 5 - 0 ratings