Android + Firebase:同步为异步功能 [英] Android + Firebase: synchronous for into an asynchronous function
问题描述
我正在制作一个函数(Java-Android),该函数应该返回一个包含Firebase数据的对象列表.我的问题是,在遍历for中的所有项目之后,我需要将结果发送给侦听器,看看代码:
I'm making a function (Java - Android) which should return me a list of objects filled with data from Firebase. My problem is that I need to send the result to the listener just after I loop through all the items in a for, take a look at the code:
final DatabaseReference beaconMessageRef = dataSnapshot.getRef().getRoot().child("region_messages/" + regionKey);
beaconMessageRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(!dataSnapshot.exists())
FirebaseHelper.this.messageByBeaconListener.onSuccess(null);
for (DataSnapshot regionMessageDS : dataSnapshot.getChildren()) {
RegionMessage regionMessage = regionMessageDS.getValue(RegionMessage.class);
String msgKey = regionMessageDS.getKey();
final DatabaseReference messageRef = regionMessageDS.getRef().getRoot().child("messages/"+msgKey);
messageRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
Message msg = dataSnapshot.getValue(Message.class);
FirebaseHelper.this.addMessageByBeacon(msg);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
FirebaseHelper.this.messageByBeaconListener.onFail(databaseError);
}
});
}
List<Message> msgs = FirebaseHelper.this.beaconMessageList;
FirebaseHelper.this.beaconMessageList = null;
FirebaseHelper.this.messageByBeaconListener.onSuccess(msgs);
}
@Override
public void onCancelled(DatabaseError databaseError) {
FirebaseHelper.this.messageByBeaconListener.onFail(databaseError);
}
});
我需要执行以下行: FirebaseHelper.this.messageByBeaconListener.onSuccess(msgs);
在遍历for中的所有项目之后.
I need to execute this line: FirebaseHelper.this.messageByBeaconListener.onSuccess(msgs);
just after I loop through all the items in the for.
我该如何实现?
推荐答案
在Android上,无法可靠地使异步状态同步.每当您有这样做的欲望时,请深呼吸并重复第一句话.或在这里阅读我的答案:在Firebase侦听器中设置Singleton属性值
Something that is asynchronous cannot reliably be made synchronous on Android. Whenever you feel the urge to do that, take a deep breath and repeat that first sentence. Or read my answer here: Setting Singleton property value in Firebase Listener
相反,您将必须做每个人都要做的事情:将需要数据的代码移到数据可用时触发的回调中.
Instead you will have to do what everyone does: move the code that needs the data into the callback that is triggered when the data is available.
在您的情况下,这有点棘手,因为您要加载多个项目.幸运的是,尽管您知道需要加载多少个项目.因此,如果您引入一个计数器来跟踪已加载了多少物品,那么您将知道完成的时间:
In your case it is a bit trickier, since you're loading multiple items. Luckily though you know how many items you need to load. So if you introduce a counter to track how many items have loaded, you will know when you're done:
final DatabaseReference beaconMessageRef = dataSnapshot.getRef().getRoot().child("region_messages/" + regionKey);
beaconMessageRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(!dataSnapshot.exists())
FirebaseHelper.this.messageByBeaconListener.onSuccess(null);
for (DataSnapshot regionMessageDS : dataSnapshot.getChildren()) {
RegionMessage regionMessage = regionMessageDS.getValue(RegionMessage.class);
String msgKey = regionMessageDS.getKey();
final Integer[] counter = new Integer[1];
final DatabaseReference messageRef = regionMessageDS.getRef().getRoot().child("messages/"+msgKey);
messageRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot innerSnapshot) {
if(innerSnapshot.exists()){
Message msg = innerSnapshot.getValue(Message.class);
FirebaseHelper.this.addMessageByBeacon(msg);
}
counter[0] = new Integer(counter[0].intValue()+1);
if (counter[0].equalTo(dataSnapshot.numChildren()) {
List<Message> msgs = FirebaseHelper.this.beaconMessageList;
FirebaseHelper.this.beaconMessageList = null;
FirebaseHelper.this.messageByBeaconListener.onSuccess(msgs);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
FirebaseHelper.this.messageByBeaconListener.onFail(databaseError);
}
});
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
FirebaseHelper.this.messageByBeaconListener.onFail(databaseError);
}
});
请参阅以下答案以获取对单个元素数组的解释: https://stackoverflow.com/a/5977866/209103
See this answer for an explanation of the single-element-array: https://stackoverflow.com/a/5977866/209103
这篇关于Android + Firebase:同步为异步功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!