Firebase在不同设备/ Android版本上以不同顺序返回子节点的键

我从Firebase数据库获取数据快照以检索用户列表,但返回的键的顺序因使用的Android版本/设备而异。

出于演示目的,我缩短了方法,但基本上如下:

public void getUsers(){ Firebase ref = new Firebase("https://myFirebaseID.firebaseio.com"); final Firebase userRef = ref.child("users"); userRef.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { snapshot.toString(); } }); } 

它是我在快照对象(snapshot.toString())上调用toString()获得的数据,它改变了顺序。

我在4台设备上试过了。 2个运行的Lollipop(Nexus 7 5.1.1和Galaxy s4 5.01)以相同的顺序返回数据。 另外两个设备(HTC Sensation 4.0.3和Motorola G2 4.4.4)以相同的顺序返回数据(但与Lollipop设备的顺序不同)。

所使用的代码没有区别,并且在检索快照时数据库中的数据完全没有变化。

以下是4.4.4和4.0.3设备上的数据顺序:

 DataSnapshot { key = users, value = { 114585619420240714499={ **userIDOfCUser**=114585619420240714499, **NameOfCUser**=testName, **EmailOfCUser**=testerfireapp@gmail.com, **friends**={ 103902248954972338254={ **userIDOfFriend**=103902248954972338254, **NameOfFriend**=testName2 } } } 

以下是5.1.1和5.01设备上的数据顺序:

 DataSnapshot { key = users, value = { 114585619420240714499={ **NameOfCUser**=testName, **userIDOfCUser**=114585619420240714499, **friends**={ 103902248954972338254={ **NameOfFriend**=testName2 , **userIDOfFriend**=103902248954972338254 } }, **EmailOfCUser**= testerfireapp@gmail.com } } } 

为什么数据以不同的顺序交付,具体取决于所使用的Android版本/设备? 还有另一个我不知道的区别吗?

编辑:按照以下方式迭代快照时,不同版本的Android仍会保持不同的键顺序:

 public void getUsers2(){ Firebase ref = new Firebase("https://myFirebaseID.firebaseio.com"); final Firebase userRef = ref.child("users"); userRef.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { for (DataSnapshot keys : snapshot.getChildren()) { //String to temporarily store the whole child of the inidividual user's DB node ----> It still produces different order of the keys String tempKey = keys.getValue().toString(); //The problem persists if I code it like this as well. String tempKey2 = snapshot.child(keys.getKey()).getValue().toString(); } } }); } 

Firebase的REST API文档包含此警告 :

使用REST API时,过滤后的结果将以未定义的顺序返回,因为JSON解释器不会强制执行任何排序。 如果您的数据顺序很重要,则应在从Firebase返回结果后对应用程序中的结果进行排序。

换句话说:JSON对象中的属性可以按任何顺序排列。 JSON解析器可以根据需要自由重新排列它们。

您没有使用REST API,而是使用Firebase Android SDK。 如果隐藏此类重新排序或(当无法隐藏它时)所有Firebase SDK都会小心谨慎地告诉您明确订单是什么(例如onChildAdded回调的previousChildName参数 )

但是从您显示的数据看来,您似乎正在解析dataSnapshot.toString()的输出。 虽然这是完全有效的,但它确实意味着您自己选择处理订购。 一般来说,最好坚持使用Firebase Android SDK的方法,因为它们处理的事情就像为您订购:

 public void onDataChange(DataSnapshot snapshot) { for (DataSnapshot friendSnapshot: snapshot.getChildren()) { System.out.println(friendSnapshot.child("NameOfFriend").getValue()); } } 

更新

从您的更新看起来您似乎有一个用户查询,然后想要循环他们的朋友。 使用Firebase Android API,您可以执行以下操作:

 Firebase ref = new Firebase("https://myFirebaseID.firebaseio.com"); final Firebase userRef = ref.child("users"); userRef.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot userSnapshot) { DataSnapshot friendsSnapshot = userSnapshot.child("friends"); for (DataSnapshot friendSnapshot : friendsSnapshot.getChildren()) { System.out.println(friendSnapshot.child("NameOfFriend").getValue()); } } });