Reputation: 128
I'm trying to implement firebase database in my app, but I'm having problems in retrieving data from multiple nodes at same time and updating the ui. I'm storing all the Firebase methods in a separate class. here is an example of one of the methods to retrieve one datum from a node.
public static void getTrainerCity(final Trainer trainer) {
dbref.child(USER_CITY).child(trainer.getId()).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
trainer.setCity(dataSnapshot.getValue(String.class));
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Then, to get for example one complete trainer, I do
public static void getTrainer(final boolean isAthlete, final String trainerId, Trainer trainer) {
trainer.setId(trainerId);
getTrainerCity(trainer);
getTrainerName(trainer);
getTrainerAge(trainer);
getTrainerNumber(trainer);
getTrainerEmail(trainer);
getTrainerGym(trainer);
getTrainerPhoto(trainer);
getTrainerStudyDegree(trainer);
getTrainerDescription(trainer);
if(!isAthlete) {
getTrainerAthletes(trainer);
}
}
when I call this method in UI, I'm not getting the entire Trainer object in one shot as those methods don't run on the main thread. This means that the trainer is constantly updated. However, I want to notify the UI only when all fields of the object related to the method have been set (I have to populate lists and initialize user). How would you do this?
I thought about attaching listeners, but it seems like I need a tremendous amount of them. Thank you guys
EDIT: This is how Db is structured
Upvotes: 3
Views: 1565
Reputation: 3654
You should get trainer node first and then parse the fetched data. I assume you have a Trainer node which contains all the info (city, name, age, ...)
public static void getTrainer(final Trainer trainer) {
dbref.child(trainer_node).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Trainer trainer = dataSnapshot.getValue(Trainer.class);
String name = trainer.getName();
String city = trainer.getCity();
int age = trainer.getAge();
.
.
.
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
EDIT: Data structure maybe like this
-users_node
--user1
---id:userid
---name: username
---city:usercity
---email:useremail
---workouts
----workoutid1:true
----workoutid2:true
--user2
---id:..
-athletes_node
--user1:true
--user2:true
--userX:true
-workouts_node
--workoutid1
---workout details here
--workoutid2
---workout details here
Upvotes: 1
Reputation: 10350
It's scenarios like this where RxJava
shines.....what you could do is wrap firebase queries in Observable.create()
and then use something like RxJava zip
operator to combine all the queries. The alternative (to be avoided if possible) is to nest all the queries which leads to dreaded callback hell
For example you might have something like following for getTrainerCity
public static Observable<String> getTrainerCity(int trainerId) {
return Observable.create(subscriber -> {
dbref.child(USER_CITY).child(trainerId).addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
String city = dataSnapshot.getValue(String.class);
subscriber.onNext(city);
subscriber.onCompleted();
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
});
}
Upvotes: 2