FrangSierra / RxFirebase

Rxjava 2.0 wrapper on Google's Android Firebase library.
MIT License
514 stars 71 forks source link

Question #44

Closed jemshit closed 6 years ago

jemshit commented 6 years ago

Hi, i am having difficulty when querying multiple tables and listening for changes. Table1 is:

user_id: {
    roomId1:true,
    roomId2:true
}

and Table2 is:

roomId1:{},
roomId2{},

I have to query table1 first and get roomIDs of user. Then get details of each room from table2. Then listen for changes of table1 (if table1 changes, i have to requery table2).

Initially i have used RxFirebaseQuery but it does not listen for changes.

jemshit commented 6 years ago
// returns Observable<List<Room>>
RxFirebaseDatabase.observeValueEvent(userRoomsTable.child(myUserId))
                                    .subscribeOn(Schedulers.io())
                                    .flatMap(dataSnapshot -> {
                                        if (dataSnapshot != null && dataSnapshot.getChildrenCount() > 0) {
                                            List<String> roomIds = new ArrayList<>();
                                            for (DataSnapshot itemSnapshot : dataSnapshot.getChildren()) {
                                                roomIds.add(itemSnapshot.getKey());
                                            }

                                            return Flowable.fromIterable(roomIds)
                                                    .flatMap(roomId -> {
                                                        return RxFirebaseDatabase.observeValueEvent(roomsTable.child(roomId), Room.class);
                                                    })
                                                    .subscribeOn(Schedulers.io())
                                                    .buffer((int) dataSnapshot.getChildrenCount());
                                        } else
                                            return Flowable.just(Collections.<Room>emptyList());
                                    })
                                    .toObservable();

This code returns List<Room> initially, and if room is deleted from userRoomsTable, it returns new List<Room>. So far so good. But if specific Room is updated from roomsTable (e.g. last message field of Room), it does not produce updated List<Room> because of buffer((int) dataSnapshot.getChildrenCount());

FrangSierra commented 6 years ago

When a query returns you a result that doesnt exist, if its a Maybe(like ObserveSinglevalueEvent) it will call to "onComplete". In other hand if you are using a ObserveValueEvent it will return you a DataSnapshot where Exists() is false. Your problem is that you are mapping the observeValueEvent, and the mapping is filtered by existing dataSnapshots. Thats why your last event is never emmited.

Change return RxFirebaseDatabase.observeValueEvent(roomsTable.child(roomId), Room.class); for return RxFirebaseDatabase.observeValueEvent(roomsTable.child(roomId)); and check the dataSnapshot.exist() in your subscribe.

Happy coding ;)