Firebase / Android - 等待所有线程完成响应
Firebase / Android - Wait for all thread finish for response
我有以下代码:
public synchronized void next(final RoomListQueryResultHandler handler) {
this.setLoading(true);
roomList = new ArrayList<Room>();
this.database.child("members").child(this.mUser.getUid()).child("rooms")
.limitToFirst(this.mLimit)
.startAt(this.currentPage * this.mLimit)
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
RoomListQuery.this.setLoading(false);
//mListAdapter.setLoading(false);
if (!dataSnapshot.hasChildren()) {
RoomListQuery.this.currentPage--;
}
for (DataSnapshot ds : dataSnapshot.getChildren()) {
Room room = ds.getValue(Room.class);
//roomList.add(Room.upsert(room));
Room.getRoom(room.getId(), new Room.RoomGetHandler() {
@Override
public void onResult(Room room, customException e) {
if (e != null) {
// Error!
e.printStackTrace();
return;
}
roomList.add(room);
}
});
handler.onResult(roomList, (customException) null);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
handler.onResult((List) null, new customException(databaseError.toString()));
}
});
}
}
如果他们看到了,我有两个处理程序,首先我从 Firebase 调用 "rooms" 的列表,然后我在其他查询中获取每个处理程序的详细信息。
问题是响应是一个空列表,因为函数不等待房间的所有查询细节被执行,所以变量 roomList 总是 returns 空。
知道我可以实现什么,或者可以使用什么其他方法来解决它?
非常感谢!
你好。
根据您的应用程序的结构,您可能希望更改数据库设计,这样就无需为从第一个查询中检索到的每个房间执行额外的 Firebase 查询。
//mListAdapter.setLoading(false);
如果您要创建一个列表视图,其中每一行都来自 /members/<user_id>/rooms
Firebase 节点,那么显示该列表所需的最小房间属性是什么?如果只是房间名称、照片 url、所有者、room_id 等几项内容,您最好从原始来源复制这些内容。然后单击这些行之一可以触发您作为 Room.getRoom(room.getId(), new Room.RoomGetHandler() { ... });
的一部分的原始 附加 Firebase 查询,以导航到新屏幕/一次显示包含完整房间详细信息的模式检索到。
更新
为了解决您关于需要额外数据的评论,在这种情况下,作为 Room
class 的一部分,我将包含一个额外的布尔值 _loadedDetails
,最初设置为 false。因此,为了在列表中渲染一个房间,当 _loadedDetails
当前为 false 时,只显示一个加载微调器。这样您仍然可以执行那些额外的查询,并在完成后根据索引更新 roomList
内的适当 Room
对象。像这样:
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
RoomListQuery.this.setLoading(false);
//mListAdapter.setLoading(false);
if (!dataSnapshot.hasChildren()) {
RoomListQuery.this.currentPage--;
}
int i = 0;
for (DataSnapshot ds : dataSnapshot.getChildren()) {
Room room = ds.getValue(Room.class);
roomList.add(room); // here instead
updateRoom(room, i);
i++;
}
handler.onResult(roomList, (customException) null);
}
...
// outside of the ValueEventListener
public void updateRoom(room, index) {
Room.getRoom(room.getId(), new Room.RoomGetHandler() {
@Override
public void onResult(Room room, customException e) {
if (e != null) {
// Error!
e.printStackTrace();
return;
}
room._loadedDetails = true; // make that publicly accessible boolean, or include a setter method instead
roomList.set(index, room);
}
});
}
我有以下代码:
public synchronized void next(final RoomListQueryResultHandler handler) {
this.setLoading(true);
roomList = new ArrayList<Room>();
this.database.child("members").child(this.mUser.getUid()).child("rooms")
.limitToFirst(this.mLimit)
.startAt(this.currentPage * this.mLimit)
.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
RoomListQuery.this.setLoading(false);
//mListAdapter.setLoading(false);
if (!dataSnapshot.hasChildren()) {
RoomListQuery.this.currentPage--;
}
for (DataSnapshot ds : dataSnapshot.getChildren()) {
Room room = ds.getValue(Room.class);
//roomList.add(Room.upsert(room));
Room.getRoom(room.getId(), new Room.RoomGetHandler() {
@Override
public void onResult(Room room, customException e) {
if (e != null) {
// Error!
e.printStackTrace();
return;
}
roomList.add(room);
}
});
handler.onResult(roomList, (customException) null);
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
handler.onResult((List) null, new customException(databaseError.toString()));
}
});
}
}
如果他们看到了,我有两个处理程序,首先我从 Firebase 调用 "rooms" 的列表,然后我在其他查询中获取每个处理程序的详细信息。
问题是响应是一个空列表,因为函数不等待房间的所有查询细节被执行,所以变量 roomList 总是 returns 空。
知道我可以实现什么,或者可以使用什么其他方法来解决它?
非常感谢! 你好。
根据您的应用程序的结构,您可能希望更改数据库设计,这样就无需为从第一个查询中检索到的每个房间执行额外的 Firebase 查询。
//mListAdapter.setLoading(false);
如果您要创建一个列表视图,其中每一行都来自 /members/<user_id>/rooms
Firebase 节点,那么显示该列表所需的最小房间属性是什么?如果只是房间名称、照片 url、所有者、room_id 等几项内容,您最好从原始来源复制这些内容。然后单击这些行之一可以触发您作为 Room.getRoom(room.getId(), new Room.RoomGetHandler() { ... });
的一部分的原始 附加 Firebase 查询,以导航到新屏幕/一次显示包含完整房间详细信息的模式检索到。
更新
为了解决您关于需要额外数据的评论,在这种情况下,作为 Room
class 的一部分,我将包含一个额外的布尔值 _loadedDetails
,最初设置为 false。因此,为了在列表中渲染一个房间,当 _loadedDetails
当前为 false 时,只显示一个加载微调器。这样您仍然可以执行那些额外的查询,并在完成后根据索引更新 roomList
内的适当 Room
对象。像这样:
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
RoomListQuery.this.setLoading(false);
//mListAdapter.setLoading(false);
if (!dataSnapshot.hasChildren()) {
RoomListQuery.this.currentPage--;
}
int i = 0;
for (DataSnapshot ds : dataSnapshot.getChildren()) {
Room room = ds.getValue(Room.class);
roomList.add(room); // here instead
updateRoom(room, i);
i++;
}
handler.onResult(roomList, (customException) null);
}
...
// outside of the ValueEventListener
public void updateRoom(room, index) {
Room.getRoom(room.getId(), new Room.RoomGetHandler() {
@Override
public void onResult(Room room, customException e) {
if (e != null) {
// Error!
e.printStackTrace();
return;
}
room._loadedDetails = true; // make that publicly accessible boolean, or include a setter method instead
roomList.set(index, room);
}
});
}