联接扁平化数据是一种常见的用例,也在documentation中进行了描述。但是文档显示了一个简单的示例,该示例不是实时的,它对更改没有反应。我正在寻找更可靠的实现。我认为RxJava对此非常理想。
考虑以下Firebase结构:
{
"messages": {
"group_id_1": {
"message_id_1": {
"text": "Hello",
"author": "uid_1"
}
}
},
"users": {
"uid_1": {
"name": "David"
}
},
"rooms": {
"room_id_1": {
"name": "General",
"members": {
"uid_1": true
}
}
}
}
我在这里看到两个用例:
Observable<Message>
,当我订阅它时,依赖项(那些消息的用户)也将在某些缓存中被订阅。当显示消息时,我可以从缓存中获取作者的姓名。 Observable<User>
,当我订阅它时,它将首先订阅 session 室的成员,然后再订阅单个用户。 您知道可以执行此操作的库/解决方案吗?
或者,如果我创建了一个,您会用吗?
最佳答案
我打算提出这个问题的一个变种,但似乎最好是在这个问题的基础上...我将描述至少部分是上述问题的答案,但也有一个缺点看到。
使用上述数据模型,我们可能会像下面这样围绕firebase查询创建RxJava包装器,以获取特定房间的成员 key 列表以及特定成员的详细信息(请注意在onCompleted()
中使用subscriber.getMemberInfo
...稍后会详细介绍!)。
public Observable<String> getRoomMembers(String roomId) {
return Observable.create(subscriber -> {
databaseReference.child(roomId + "/members").addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot childSnapshot: dataSnapshot.getChildren()) {
String userId = childSnapshot.getKey()
subscriber.onNext(userId);
}
subscriber.onCompleted();
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
});
}
public Observable<Member> getMemberInfo(String memberId) {
return Observable.create(subscriber -> {
databaseReference.child(memberId).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Member member = dataSnapshot.getValue(Member.class);
subscriber.onNext(member);
subscriber.onCompleted();
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
});
}
然后,我们可以执行以下操作来获取特定房间的
Member
列表(已在isActive
中添加了Member
属性,以显示我们还如何过滤得到的结果)。 getRoomMembers(roomId)
.flatMap(memberId -> getMemberInfo(memberId))
.filter(Member::isActive)
.toList()
.subscribe(members -> {
});
因此,以上工作到了一定程度。问题是我必须在
subscriber.onCompleted()
中调用getMemberInfo
才能使上述对flatMap
的调用正常工作....这意味着对Member
数据的任何后续更改都不会触发上述订阅中的更新。对RxJava
和Firebase
来说相对较新,因此可能缺少明显的内容。