0

In Firebase, when applying the principles of flattened data structure explained here.

If I have the structure used in their example:

  // Chats contains only meta info about each conversation
  // stored under the chats's unique ID
  "chats": {
    "one": {
      "title": "Historical Tech Pioneers",
      "lastMessage": "ghopper: Relay malfunction found. Cause: moth.",
      "timestamp": 1459361875666
    },
    "two": { ... },
    "three": { ... }
  },

  // Conversation members are easily accessible
  // and stored by chat conversation ID
  "members": {
    // we'll talk about indices like this below
    "one": {
      "ghopper": true,
      "alovelace": true,
      "eclarke": true
    },
    "two": { ... },
    "three": { ... }
  },
  "users": {
    "ghopper": {
      "name": "user_name",
      "age": 28
    },
    "alovelace": { ... },
    "eclarke": { ... }
  }
}

let's say that I want to show the list of members of channel one with all their details. That means that I have to firstly retrieve all children at the location members/one, and then query each of the users ID individually.

That means that if I want to show them in a recycler view, the retrieving of data being asynchronous, user experience may not be the best:

Which would in my case be an implementation like:

@Override
    public void onBindViewHolder(final UserViewHolder viewHolder, int position) {
    //getKey(position) just retrieve the key of current member in my adapter array
          FirebaseDatabase.getInstance().getReference("users").child(getKey(position)).addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                User user = dataSnapshot.getValue(User.class);
                viewHolder.setName(user.getName());
                viewHolder.setPersonAge(user.getAge());
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
    }

This is not ideal, but I cannot see another approach. Loading each member before launching the activity introduce the problem of knowing when all the users profiles have been retrieved from the database.

Any advice is welcomed.

AL.
  • 36,815
  • 10
  • 142
  • 281
gbaccetta
  • 4,449
  • 2
  • 20
  • 30
  • Why do you say that the user experience would not be good? Joining data like this is a common operation with Firebase. While the join is asynchronous, it *is* executed in order and fast. See my answers about [joining](http://stackoverflow.com/questions/34559171/coupling-firebaserecyclerviewadapter-to-a-boolean-string-map-entry) and the [speed of such joins](http://stackoverflow.com/questions/35931526/speed-up-fetching-posts-for-my-social-network-app-by-using-query-instead-of-obse/35932786#35932786) – Frank van Puffelen Oct 11 '16 at 13:30
  • what would happen if connection is slow ? The viewholder would have old data from previous item beeing showed or the updating of the data happens after the user scrolled down... – gbaccetta Oct 11 '16 at 13:40
  • also I have a doubt about what happen if I have lots of users and you would scroll really fast.... could an asynchronous update happen on the wrong position in the recycler view (since viewholders are reused by definition) ? – gbaccetta Oct 11 '16 at 13:41
  • what I usually do is to retrieve the `User` data using `ChildEventListener` in the activity/fragment, put it to the list for the adapter, and then call `adapter.notifyDataSetChanged()`. If there is any change to the `User`, you can easily re-set the value to the list in the `onChildChanged` method. – Wilik Oct 11 '16 at 13:52
  • @Wilik that does not work in my case because the ChildEventListener is set to the "members/one" node. If I use it on the user node I would retrieve all the users in the database and not only those beeing in the group I'm considering ("one" in this example). – gbaccetta Oct 11 '16 at 14:58

0 Answers0