Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a FirebaseRecyclerAdapter with a dynamic reference in Android? [duplicate]

I know how to use a FirebaseRecyclerAdapter on a list of items in Firebase. I also know how to get Firebase data from multiple locations using indices. But I do not know how to combine this with a FirebaseRecyclerAdapter.

I have a simple data structure where users can be friends:

"users": {
  "user1": {
    "name": "name",
    "friends": {
      "user2": "true"
      }
    }
  "user2": {
    "name": "name",
    "friends": {
      "user1": "true"
      }
    }
  }

I use unique ids for the usernames. In this simple example, user 1 and user 2 are friends. What I want to do, is get a list of all the names (and later maybe more) using a FirebaseRecyclerAdapter. Normally, I would get a list by obtaining the user id's under "friends" and then using those id's to navigate to their names. In Java, it would look like this:

Firebase ref = new Firebase("<reference>");
ref.child("users/user1/friends").addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot snapshot) {
    String userId = snapshot.getKey();
    ref.child("users/" + userId + "/name").addListenerForSingleValueEvent(new ValueEventListener() {
      @Override
      public void onDataChange(DataSnapshot snapshot) {
        System.out.println(snapshot.getValue());
      }
      @Override
      public void onCancelled(FirebaseError firebaseError) {
        // Do something here
      }
    });
  }
});

But when using a FirebaseRecyclerAdapter, you only get to define one URL. The adapter will make a list based on the items in that single place.

Is there a way to adjust the adapter so that it reads data from multiple places, the same way that the example above does? Or is there a way to make a dynamic ref variable that points only to the user id's that are also stored in the current user "friends" list? I was thinking about using the equals() method, but I cannot figure out how exactly.

Another way would be storing the user names also in the "friends" list. But that would not improve the data structure. I would have to change the names in two places every time (and maybe photo's later on) and it would introduce more redundancy.

Does anybody have a solution for this problem? I could not find an answer anywhere but it seems like a common pattern. And apart from just making it work, how do I do it efficiently?

like image 647
TomasKok Avatar asked Mar 26 '16 13:03

TomasKok


1 Answers

You'll need to join the data, by attaching a addListenerForSingleValueEvent().

FirebaseRecyclerViewAdapter<Boolean, ItemViewHolder> adapter = new FirebaseRecyclerViewAdapter<Boolean, ItemViewHolder>(
    Boolean.class, android.R.layout.two_line_list_item, ItemViewHolder.class, friendsRef){
    protected void populateViewHolder(final ItemViewHolder viewHolder, Boolean model, int position) {
        String key = this.getRef(position).getKey();
        ref.child("users").child(key).addListenerForSingleValueEvent(new ValueEventListener() {
            public void onDataChange(DataSnapshot dataSnapshot) {
                String name = dataSnapshot.child("name").getValue(String.class);
                ((TextView)viewHolder.itemView.findViewById(android.R.id.text1)).setText(name);
            }

            public void onCancelled(FirebaseError firebaseError) { }
        });
    }
};

I've added an activity Activity36235919 to demonstrate this to my sample repo.

After making it work I realized that I'd answered this before in Coupling FirebaseRecyclerViewAdapter to a Boolean/String Map.Entry, so I'll mark your question as a duplicate.

like image 105
Frank van Puffelen Avatar answered Nov 15 '22 15:11

Frank van Puffelen