简体   繁体   中英

How can I make last contacted user appear on top of list in recyclerview each time a message is sent or received?

I am building a Chat application using Firebase database. I have been able send and receive chats, I have also been able to get the users contacted under java class ChatsActivty The problem is that the users in my ChatsActivity are only ordered alphabetically even when a new message is sent or received ie onDataChange, the list remains the same. I want user latest contacted to appear on top every time a message is sent or received.

My code is as shown below:

ChatsActivity.java

public class ChatsActivity extends AppCompatActivity {

    private RecyclerView chatsRecyclerview;

    private AdapterUsers userAdapter;
    private List<ModelUser> mUsers;

    FirebaseUser fUser;
    DatabaseReference reference;

    private List<String> userList;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_chats);

        ActionBar actionBar = getSupportActionBar();
        actionBar.setTitle("Messages");
        actionBar.setDisplayHomeAsUpEnabled(true);

        chatsRecyclerview = findViewById(R.id.chats_recyclerview);

        //Linear Layout for RecyclerView
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(ChatsActivity.this);
        //recyclerview properties

        chatsRecyclerview.setHasFixedSize(true);
        chatsRecyclerview.setLayoutManager(linearLayoutManager);

        fUser = FirebaseAuth.getInstance().getCurrentUser();
        userList = new ArrayList<>();

        reference = FirebaseDatabase.getInstance().getReference("Chats");
        Query query = reference.orderByKey().limitToLast(10000);
        query.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                userList.clear();

                for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
                    ModelChat chat = dataSnapshot.getValue(ModelChat.class);

                    if (chat.getSender().equals(fUser.getUid())) {
                        userList.add(chat.getReceiver());
                    }
                    if (chat.getReceiver().equals(fUser.getUid())) {
                        userList.add(chat.getSender());
                    }
                }
                readChats();
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {

            }
        });

    }

    private void readChats() {
        mUsers = new ArrayList<>();
        reference = FirebaseDatabase.getInstance().getReference("Users");

        reference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                mUsers.clear();

                for (DataSnapshot ds : snapshot.getChildren()) {
                    ModelUser user = ds.getValue(ModelUser.class);

                    for (String uid : userList) {
                        assert user != null;
                        if (user.getUid().equals(uid)) {
                            mUsers.add(user);
                            break;
                        }
                    }

                }
                userAdapter = new AdapterUsers(ChatsActivity.this, mUsers);
                chatsRecyclerview.setAdapter(userAdapter);
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {

            }
        });
    }

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        if (item.getItemId() == android.R.id.home) {
            startActivity(new Intent(ChatsActivity.this, HomeActivity.class));
            ChatsActivity.this.finish();
        }

        return super.onOptionsItemSelected(item);
    }

}

My AdapterUsers code:

public class AdapterUsers extends RecyclerView.Adapter<AdapterUsers.MyHolder>{

Context context;
List<ModelUser> userList;

//Constructor > Generate
public AdapterUsers(Context context, List<ModelUser> userList) {
    this.context = context;
    this.userList = userList;
}

@NonNull
@Override
public MyHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    //Inflate layout (row_user)
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_users, parent, false);

    return new MyHolder(view);
}

@Override
public void onBindViewHolder(@NonNull MyHolder holder, int position) {
    //get data
    String userUID = userList.get(position).getUid();
    String userProfilePic = userList.get(position).getProfilepic();
    String userName = userList.get(position).getFirstname() + " " + userList.get(position).getLastname();
    String userNickname = userList.get(position).getNickname();
    String userStatus = userList.get(position).getStatus();

    //set data
    holder.mNameTv.setText(userName);
    holder.mNicknameTv.setText(userNickname);
    holder.mStatusTv.setText(userStatus);

    Glide
            .with(context)
            .load(userProfilePic)
            .apply(RequestOptions.circleCropTransform())
            .into(holder.mAvatarIv);

    //Handle item click
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            /*Click user from user list to start conversation
             *Start Activity by putting UID of receiver
             *we will use that UID to identify the user we are gonna chat */

            Intent intent = new Intent(context, ChatActivity.class);
            intent.putExtra("userUid", userUID);
            context.startActivity(intent);

        }
    });

}

@Override
public int getItemCount() {
    return userList.size();
}

class MyHolder extends RecyclerView.ViewHolder {

    ImageView mAvatarIv;
    TextView mNameTv, mNicknameTv, mStatusTv;

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

        mAvatarIv = itemView.findViewById(R.id.avatarIv);
        mNameTv = itemView.findViewById(R.id.nameTv);
        mNicknameTv = itemView.findViewById(R.id.nicknameTv);
        mStatusTv = itemView.findViewById(R.id.statusTv);

        mStatusTv.setEllipsize(TextUtils.TruncateAt.MARQUEE);
        mStatusTv.setSelected(true);
        mStatusTv.setSingleLine(true);

    }
}

}

Currently, you are querying your realtime database and ordering by its key name. To sort the RecyclerView list, you can try two approaches from here:

  1. Querying in such a way that you get results ordered by the last message timestamp.
  2. Manually process and sort at the RecyclerView adapter to display latest chat at the top.

For approach one, you can try using your query like this:

Query query = reference.orderByChild("last_msg_time_stamp").limitToLast(10000);

Here, last_msg_time_stamp might be the key inside Chats/$your_keys which holds the last timestamp for that conversation. For approach two, I would say that in your adapter, you are taking this data and putting it. But before binding this data into list, you need to sort your list on the basis of your last message timestamp for all of the keys.

In my view, It would be beneficial to use approach one, since, it would be less processing-intensive way for the users. The realtime database would be pre-processing and the required list for you already.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM