Synchronyze
Synchronyze

Reputation: 128

Retrieve data in parallel from Firebase Database and sync with UI in Android

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 This is how db is structured

Upvotes: 3

Views: 1565

Answers (2)

ugur
ugur

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

John O'Reilly
John O'Reilly

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

Related Questions