从firebase数据库获取数据后,ArrayList显示为空

时间:2017-06-01 18:00:36

标签: android firebase asynchronous firebase-realtime-database

我正在我的应用中实现firebase。请参考下面的图片作为我的数据库的参考。

The SLC Structure

我有一个SLC名称数组,我需要生成一个SLC键的arrayList。所以我试图创建一个特定SLC密钥的arrayList。请参阅以下代码一次。

for (int i = 0; i < arr.size(); i++)
{
    Query query = ref.child(pref.getString("groupSelectedDCU", "") + "/" + "DeviceList")
                     .orderByChild("name")
                     .equalTo(arr.get(i));
    query.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for (DataSnapshot child: dataSnapshot.getChildren())
            {
                Log.d("arrID", child.getKey() + "");
                arrID.add(child.getKey());
            }

            Log.d("arrID", Arrays.toString(arrID.toArray()));
        }

        @Override
        public void onCancelled(FirebaseError firebaseError) {
        }
    });
}
Log.d("arrID", Arrays.toString(arrID.toArray()));

这里我试图将所有SLC密钥添加到arrID arraylist中。但是在访问arrayList时,它返回一个空数组。我错过了什么或者我是否需要添加更多听众?需要你的帮助。

1 个答案:

答案 0 :(得分:2)

你误解了addListenerForSingleValueEvent是如何运作的。当查询响应最终从网络到达时,提供的ValueEventListener方法将在后台异步调用 。因此,当最后一个语句运行时(在 for循环之后):

...
Log.d("arrID", Arrays.toString(arrID.toArray()));

arrID 仍然为空,因为尚未调用任何onDataChange方法。

替代解决方案。如果您需要等到所有查询完成,请尝试以下方法:

List<String> arrID = ArrayList<String>();
int remainingQueries = arr.size(); 
for (int i = 0; i < arr.size(); i++) {
    Query query = ...
    query.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for (DataSnapshot child: dataSnapshot.getChildren()) {
                Log.d("arrID", child.getKey() + "");
                arrID.add(child.getKey());
            }
            Log.d("arrID", Arrays.toString(arrID.toArray()));
            if (--remainingQueries == 0) onQueriesDone(arrID);
        }
        @Override
        public void onCancelled(FirebaseError firebaseError) { }
    });
}

完成后会调用此方法:

private void onQueriesDone(List<String> arrID) {
    Log.d("arrID", Arrays.toString(arrID.toArray()));
}

特别是,我们不需要同步锁来访问共享计数器remainingQueries,因为所有Firebase回调都是在主线程上触发的。