Joining flattened data is a common use case also described in the documentation. But the documentation shows a simple example which is not real-time, it doesn't react to changes. I'm looking for a more robust implementation. I think RxJava is ideal for this.
Consider following Firebase structure:
{
"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
}
}
}
}
I see two use-cases here:
Observable<Message>
and when I subscribe to it, dependencies (users for those messages) will be subscribed as well in some cache. When I'm showing the messages, I can get author's names from the cache.Observable<User>
and when I subscribe to it, it will first subscribe to room's members and then to individual users.Do you know about library/solution which could do that?
Or would you use it if I created one?
I was going to pose a variation of this question but seemed like it might be better to build on top of this one...I'll describe what is hopefully at least partially the answer to above question but also then a shortcoming I'm seeing.
Using above data model we might have something like following to create RxJava wrapper around firebase query to get list of member keys for particular room and for getting details for particular member (note use of onCompleted()
in subscriber.getMemberInfo
...more on that later!).
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) {
}
});
});
}
What we can then do use something like following to get list of Member
s for particular room (have added isActive
property to Member
to show how we also filter results we get).
getRoomMembers(roomId)
.flatMap(memberId -> getMemberInfo(memberId))
.filter(Member::isActive)
.toList()
.subscribe(members -> {
});
So, the above works up to a point. The issue is that I had to call subscriber.onCompleted()
in getMemberInfo
for the above call to flatMap
to work....which then means that any subsequent changes to Member
data isn't triggering update in the above subscription. Am relatively new to RxJava
and Firebase
so might be missing something obvious.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With