java – How to sort Firestore RecyclerView Items with a value that is not in the "Query-Collection"? (Social Leaderboard)-ThrowExceptions

Exception or error:

I have a RecyclerView adapter which should display all the users friends with their score, so basically a social leaderboard. With the adapter I get the uids from the friends and then make a query in the onBindViewHolder to get the avatar ids and usernames of each friend, and also his current score.

This works all fine but now I want to sort the RecyclerView after the score of the players. Since I have only the uid of each friend in the collection, not the score, I can’t use this code:

Query query = userRef.orderBy("uid", Query.Direction.ASCENDING);

Is there a way to sort the RecyclerView after the score of the players, without having the score in the “RecyclerView collection”? So without putting the score in the same collection where the uid is, which would lead to enormous reads and writes. I know that there is the Comparator operator but I don’t know how to use this in this context.

Here is my adapter where I want the items to be sorted by the value pointsInt

public class LeaderboardAdapter extends FirestoreRecyclerAdapter<Users, LeaderboardAdapter.UserHolder> {
    private OnItemClickListener listener;

    private String avatar_id_player_2, mUid, mCurrentUser;
    private FirebaseFirestore db = FirebaseFirestore.getInstance();
    private FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();

    public LeaderboardAdapter(@NonNull FirestoreRecyclerOptions<Users> options) {
        super(options);

    }

    @Override
    protected void onBindViewHolder(@NonNull UserHolder holder, int position, @NonNull Users model) {

        holder.textViewUsername.setText(model.getUsername());

        mCurrentUser = currentUser.getUid();

        mUid = model.getUid();

        db.collection("User").document(mUid).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                if (task.isSuccessful()) {
                    DocumentSnapshot document = task.getResult();
                    if (document != null) {

                        String username = document.getString("username");
                        avatar_id_player_2 = document.getString("avatar_id");

                        holder.textViewUsername.setText(username);
                        Picasso.get().load(avatar_id_player_2).placeholder(R.mipmap.ic_launcher).into(holder.circleImageView);

                        db.collection("User").document(mUid).collection("Points").document("Points")
                                .get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
                            @Override
                            public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                                if (task.isSuccessful()) {
                                    DocumentSnapshot document = task.getResult();
                                    if (document != null) {

                                        Integer pointsInt = document.getLong("points").intValue();
                                        holder.textViewScore.setText("" + pointsInt);
                                    }
                                }
                            }
                        });
                    }
                }
            }
        });
    }

    @NonNull
    @Override
    public UserHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.listitem_leaderboard, parent, false);
        return new UserHolder(view);
    }

    class UserHolder extends RecyclerView.ViewHolder {

       public TextView textViewUsername, textViewScore;
        CircleImageView circleImageView;

        public UserHolder(@NonNull View itemView) {
            super(itemView);

            textViewUsername = itemView.findViewById(R.id.leaderboard_username);
            circleImageView = itemView.findViewById(R.id.leaderboard_avatar);
            textViewScore = itemView.findViewById(R.id.leaderboard_score);

        }
    }

...
}

Here is how I structured my database. Here I get the value of the friends (currently this user has one friend) and then make a query as explained earlier to get the score/point value of this player:

enter image description here

And this is the collection from where I get the value that I then wanted to sort in the RecyclerView:

enter image description here

Here you can see how my RecyclerView looks right now. Here the current player has 2 friends, but the highest score is not above the lowest since it is ordered by the lid value of the players:

enter image description here

How to solve:

You need to convert your data into List of Object by creating a Model class after doing that you can sort List<Object> using

Collections.sort(userPointList, (item1, item2) -> {
    int firstUser = item1.getPoint() ? 0 : 1;
    int secondUser = item2.getPoint() ? 0 : 1;

    return first - second; // Ascending
}); // using JAVA 1_8

Ask if you need more help 🙂

Hope this will help!

Leave a Reply

Your email address will not be published. Required fields are marked *