实时数据库 return 项目的 onValue 侦听器是否按照它们添加到数据库的顺序排列?

Does the onValue listener for Realtime Database return items in the same order that they are added to the database?

我在任何地方的文档中都没有看到这一点。这个监听器 return 节点的数据是否按照添加到节点的顺序?例如,如果我添加 message1,然后是 message2,然后是 message3,此侦听器 return 数据的顺序是否与 message1、message2、message3 相同?

该应用程序使用一个名为 ChatScreen 的小部件来显示 ReceivedChats 小部件(聊天 body)和 MsgInput 小部件(聊天页脚)。没有聊天header(除非你算上应用栏?)。

ChatScreen 小部件:

class ChatScreen extends StatelessWidget {
  ChatScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final groupIDPath = 'groupChats/0exUS3P2XKFQ007TIMmm';
    return Scaffold(
      appBar: AppBar(
        leading: IconButton(
          icon: Icon(Icons.menu),
          color: Colors.white,
          onPressed: () {},
        ),
        title: Text(
          'Group Name',
        ),
        actions: [
          IconButton(
            icon: Icon(Icons.search),
            color: Colors.white,
            onPressed: () {},
          )
        ],
        backgroundColor: Color.fromRGBO(51, 50, 49, 1.0),
        elevation: 0.0,
      ),
      body: Column(
        children: [
          Expanded(
            flex: 11,
            child: Row(
              children: [
                Expanded(
                  child: ReceivedChats(groupIDPath: groupIDPath),
                ),
              ],
            ),
          ),
        ],
      )
    );
  }
}

ReceivedChats 小部件

class ReceivedChats extends StatefulWidget {
  const ReceivedChats({Key? key, required this.groupIDPath}) : super(key: key);
  final groupIDPath; 

  @override
  _ReceivedChatsState createState() => _ReceivedChatsState();
}

class _ReceivedChatsState extends State<ReceivedChats> {
  late StreamSubscription _receivedChatsStream;
  final _database = FirebaseDatabase.instance.ref();

@override
  void initState() {
    super.initState();
    _activateListeners();
  }


  void _activateListeners() {
    _receivedChatsStream = _database.child(groupIDPath).onValue.listen((event) {
      final data = event.snapshot.value;
      print('data: ' + data.toString()); //The data printed here is out of order
    });
  }

@override
  Widget build(BuildContext context) {

//...widget build stuff...//

   }
}

插入 RTDB:

class MessageDao {

  String groupIDPath; 
  DatabaseReference _messagesRef;
  FirebaseStorage _firebaseStorage;
  String _currentUID;

  MessageDao({required this.groupIDPath}):
        _messagesRef = FirebaseDatabase.instance.ref().child(groupIDPath),
        _firebaseStorage = FirebaseStorage.instance,
        _currentUID = FirebaseAuth.instance.currentUser!.uid.toString();

  //Save a single text message to RTDB
  void saveMessage(ChatData message) async {
    _messagesRef.push().set(message.toJson());
  }

RTDB中当前数据:

{
  "groupChats": {
    "0exUS3P2XKFQ007TIMmm": {
      "-N1HB8ik8RekJGQ-R9X-": {
        "filterID": "",
        "URL": "",
        "text": "1",
        "timestamp": "2022-05-04 22:08:20.782466",
        "type": "1",
        "uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
      },
      "-N1HB9LQ-NAEzp3rNr4V": {
        "filterID": "",
        "URL": "",
        "text": "2",
        "timestamp": "2022-05-04 22:08:23.323476",
        "type": "1",
        "uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
      },
      "-N1HDx2BAMNjio0o6gSU": {
        "filterID": "",
        "URL": "",
        "text": "3",
        "timestamp": "2022-05-04 22:20:35.275138",
        "type": "1",
        "uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
      },
      "-N1HDxeB9V5mvb4i4w9o": {
        "filterID": "",
        "URL": "",
        "text": "4",
        "timestamp": "2022-05-04 22:20:37.772181",
        "type": "1",
        "uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
      },
      "-N1HDy3jGshk_sLK4_oG": {
        "filterID": "",
        "URL": "",
        "text": "5",
        "timestamp": "2022-05-04 22:20:39.471453",
        "type": "1",
        "uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
      },
      "-N1HEYpMpz4L6TMDLlgr": {
        "filterID": "",
        "URL": "",
        "text": "6",
        "timestamp": "2022-05-04 22:23:14.133822",
        "type": "1",
        "uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
      },
      "-N1HE_be1sn86ZNu8KI5": {
        "filterID": "",
        "URL": "",
        "text": "7",
        "timestamp": "2022-05-04 22:23:21.450031",
        "type": "1",
        "uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
      },
      "-N1HEaW0HDvCjqexapy4": {
        "filterID": "",
        "URL": "",
        "text": "8",
        "timestamp": "2022-05-04 22:23:25.121275",
        "type": "1",
        "uid": "f1JqanGGRtd709ia4mxgaM8Apn52"
      }
    }
  }
}

你问题中的相关代码是:

_database.child('groupChats/0exUS3P2XKFQ007TIMmm').onValue.listen((event) {
  final data = event.snapshot.value;
  print('data: ' + data.toString()); //The data printed here is out of order
})

由于您在 groupChats/0exUS3P2XKFQ007TIMmm 处的数据快照上调用 event.snapshot.value,您会在该路径上获得数据的 Map。根据定义,映射中的键是无序的。


如果你想处理子节点,按照它们在数据库中return的顺序,循环event.snapshot.children:

_database.child('groupChats/0exUS3P2XKFQ007TIMmm').onValue.listen((event) {
  event.snapshot.children.forEach((snapshot) {
    print('${snapshot.key}: ${snapshot.value}');
  })
})

如果你想return从数据库中以特定顺序获取子节点,调用orderBy...方法之一。例如,要按时间戳排序:

_database.child('groupChats/0exUS3P2XKFQ007TIMmm').orderByChild('timestamp').onValue.listen((event) {
  event.snapshot.children.forEach((snapshot) {
    print('${snapshot.key}: ${snapshot.value}');
  })
})