0

So I have a question in regards to getting data from Firebase Realtime DB for Android, as it seems that completion handlers are not possible as is in iOS.

I would like to gather a list of users and their status in a particular group they are part of. My Firebase DB is structured as such:

UserInGroup
   --- GroupID
          --- UserId : true/false     (true indicates user is in the group)


Users
   --- UserId
          --- Username : String
          --- ...


GroupStatus
   --- GroupId
          --- UserId: true/false      (true indicates has admin rights)

Based on the above I would like to have a Table where it will list the user's "username" followed by the status of either admin or normal user in the group.

My code I have so far to perform the first portion of the lookup is below:

    userInGroupReference = mFirebaseDatabase.getReference("UserInGroup");

    userInGroupQuery = userInGroupReference.child("10263").orderByValue().equalTo(true);

    userInGroupQuery.addListenerForSingleValueEvent(new ValueEventListener() {

        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (dataSnapshot.exists()) {
                for (DataSnapshot resultSnapshot : dataSnapshot.getChildren()) {

                    // THIS IS WHERE I AM GETTING THE USERS ID (KEY) TO THE OTHER TWO LOOKUPS I NEED TO PERFORM
                    String userID = resultSnapshot.getKey();

                    ... What do I do now with no completion handlers!?
                }
            } else { 
                // dataSnapshot doesn't exist
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

I am just confused on how to utilize the userID I get from the first lookup and perform the additional two lookups using the userID in android!?

I mean if it was iOS I would just use completion handlers to accomplish this... how can I do so in Android?

UPDATE:

I created the interface:

private interface FirebaseCallback {

    void onSuccess(DataSnapshot dataSnapshot);

    void onStart();

    void onFailure();

}

Then created the readData function

private void readData(Query query, FirebaseCallback listener) {

    listener.onStart();

    query.addListenerForSingleValueEvent(new ValueEventListener() {

        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            if (dataSnapshot.exists()) {

                listener.onSuccess(dataSnapshot);

            } 

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }

    });

}

And placed the readData function in my OnCreate function in the Activity as such:

readData(userInGroupQuery, new FirebaseCallback() {

    @Override
    public void onSuccess(DataSnapshot dataSnapshot) {

        for (DataSnapshot snapshot : dataSnapshot.getChildren()) {

            String userId = snapshot.getKey();   

            // Get userId data from database....now you can use the retrieved data
            getUsername(userId);

            getUserStatus(userId);

        }

    }

    @Override
    public void onStart() {

        // When starting
        Log.d("ONSTART", "Started");

    }

    @Override
    public void onFailure() {

        // If failed
        Log.d("onFailure", "Failed");

    }

});

So now my question is when I call the following two (2) functions:

// Get userId data from database....now you can use the retrieved data
    getUsername(userId);

    getUserStatus(userId);

how do I get the values for for each iteration I send over for the second lookup in Firebase?

2ND UPDATE:

public void getUsername(String userId) {
    
    userReference = mFirebaseDatabase.getReference("Users");

    userQuery = userReference.child(userId).child("username");

    userQuery.addListenerForSingleValueEvent(new ValueEventListener() {

        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            if (dataSnapshot.exists()) {

                String username = dataSnapshot.getValue().toString();

            }

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }

    });

}

and the last lookup:

private void getUserStatus(String userId) {

    statusQuery.addListenerForSingleValueEvent(new ValueEventListener() {

        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            if (!dataSnapshot.exists()) {

                Boolean status = (Boolean) dataSnapshot.getValue();

            }
            
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }

    });
    
}

My goal is to have the values of the two look-ups populate a List

List<UserResults> userList;

public class UserResults {


    private String username;
    private boolean status;

    public UserResults(String username, boolean status) {

        this.username = username;
        this.status = status;

    }

}

Which is the part I am stuck on now.

Learn2Code
  • 1,642
  • 3
  • 19
  • 41
  • Instead of describing how your database looks like, please edit your question and add your database structure as a JSON file. You can simply get it by clicking the Export JSON in the overflow menu (⠇) in your [Firebase Console](https://console.firebase.google.com/u/0/project/_/database/data). – Alex Mamo Jul 28 '21 at 06:57
  • @AlexMamo i was just showing a small clip of the structure, my question is really around getting the data without being able to use completion handlers in Android and what the best practice is there. – Learn2Code Jul 28 '21 at 14:22
  • What's wrong with completion handlers in Android? – Alex Mamo Jul 28 '21 at 14:47
  • @AlexMamo i believe, based on what i have read, that completion handlers are not available in android? If they are can you show an example on how to implement it based on my question above. – Learn2Code Jul 28 '21 at 14:50
  • For each database call you perform, you need to [wait for the data to finish loading](https://stackoverflow.com/questions/47847694/how-to-return-datasnapshot-value-as-a-result-of-a-method/47853774). If you need multiple database calls, you need to use nested listers, since any code that needs data from the database, needs to be inside the onComplete/onSuccess method, or be called from there. Give it a try and tell me if it works. Ok? – Alex Mamo Jul 28 '21 at 14:54
  • @AlexMamo I have viewed your video https://www.youtube.com/watch?v=OvDZVV5CbQg&t=315s . I am new to android dev and do not know how i should implement the onComplete/onSuccess method. Can you show some code on how i can move forward, based on my code sample above?! – Learn2Code Jul 28 '21 at 19:23
  • @AlexMamo where and how do i add the onComplete/onSuccess methods? – Learn2Code Jul 28 '21 at 19:23
  • @AlexMamo I updated my question, by implementing the interface as you suggested. I am still stuck, can you please assist me further? – Learn2Code Jul 29 '21 at 00:48
  • You're good. What happens when you `getUsername(userId)` and `getUserStatus(userId)` from inside the onSuccess? – Alex Mamo Jul 29 '21 at 05:58
  • @AlexMamo I have added the last two lookups that the first lookup passes the userID as a string. So what I am needing to do is on each iteration the userID is passed to each function and the results are populated in the List item so then I can display it in a table. – Learn2Code Jul 29 '21 at 12:29
  • So to understand better, do you need a combined result of both method calls? – Alex Mamo Jul 29 '21 at 12:33
  • @AlexMamo that is correct, the `getUsername(userId)` will return the username and `getUserStatus(userId)' will return if they are an admin or not. The firebase lookups are on different nodes which is why its two functions. – Learn2Code Jul 29 '21 at 12:59

0 Answers0