A
A
Andrey Goroshko2018-08-08 15:47:33
Android
Andrey Goroshko, 2018-08-08 15:47:33

How to handle clicking on an individual RecyclerView item?

I have an application in which I receive lists of incoming and outgoing messages. These two lists are placed in RecyclerView which in turn are in fragments. When I click on a certain message, I need to go to the next activity where exactly the message that we clicked on in the list will already be shown. How it should all happen when you click on a message in the list, I must send to another activity the id of the message that comes to me from the server in the array with messages, and when I open the message display activity, I will send a request to the server to show the entire message. It is not very clear to me how to catch a click on a certain list element, and it is even more unclear how to extract the message id from this click. I also tried to implement a transition to another activity, but for some reason the intent initialization is not accepted for me. Here is my list adapter code:

class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.ViewHolder> {
    private RecyclerView recyclerViewItemClickListener;
    private List<Message> messageList;
    private Context ctx;

    MessageAdapter(List<Message> messageList, Context ctx) {
        this.messageList = messageList;
        this.ctx = ctx;

    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_of_rec_m, viewGroup, false);
        return new ViewHolder(v);

    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        Message message = messageList.get(position);
        String id = String.valueOf(message.getId());
        holder.subject.setText(message.getSubject());
        holder.from.setText(message.getSender_name());
        holder.date.setText(message.getDate());
        holder.getAdapterPosition();

здесь я пытался вставить переход на другое активити
    }

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


    class ViewHolder extends RecyclerView.ViewHolder {
        final TextView from, subject, date;
        int position = 0;

        ViewHolder(View v) {
            super(v);
            subject = v.findViewById(R.id.subject);
            from = v.findViewById(R.id.from);
            date = v.findViewById(R.id.date);
            //id = v.findViewById(R.id.id);


            v.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                }
            });
        }
    }
}

Thank you in advance for your help, valuable advice and criticism))

Answer the question

In order to leave comments, you need to log in

4 answer(s)
I
Ivan0206, 2018-08-08
@Ivan0206

Use the ButterKnife library. Recently there was a similar question, look for it, everything is painted there.

B
bakir13, 2018-08-09
@bakir13

For handling events from views, RecyclerView does not provide special methods like ListView (setOnItemClickListener or setOnItemSelectedListener).
Event handling is done manually by binding the appropriate listener to the desired view. The clicked position is obtained through the ViewHolder.getAdapterPosition() method, which returns the position that the holder displays. But, since the RecyclerView handles adapter updates asynchronously, it can happen that what is displayed on the screen may not match the contents of the adapter. If this situation occurs, then ViewHolder.getAdapterPosition() returns RecyclerView.NO_POSTION.
It turns out something like this:

class MessageAdapter extends RecyclreView.Adapter<MessageAdapter.ViewHolder> {

    private OnItemClickListener<Message> onItemClickListener;

    ...

    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
        View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_of_rec_m, viewGroup, false);
        ViewHolder holder = ViewHolder(itemView);
        // сетим слушателя нажатий на нужный компонент
        holder.itemView.setOnClickListener(v -> {
            // получаем позицию в адаптере, которой соответсвует холдер
            int position = holder.getAdapterPosition();
            // если холдер соответсвует какой-либо позиции в адаптере
            if (position != RecyclerView.NO_POSITION) {
                // уведомляем слушателя о нажатии
                fireItemClicked(position, messageList.get(position));
            }
        });
    }

    private void fireItemClicked(int position, Message item) {
        if (onItemClickListener != null) {
            onItemClickListener.onItemClicked(position, item);
        }
    }

    ...
    // суда подписываемся активитей, фрагментом, перезнтером или чем нибудь еще
    public void setOnItemClickListener(OnItemClickListener<Message> listener) {
        onItemClickListener = listener;
    }

     // реализуем подписчиком
    public interface OnItemClickListener<T> {
        void onItemClicked(int position, T item);
    }
    
}

PS: It's better to make ViewHolder static to avoid possible memory leaks.

S
Sergey, 2018-08-09
@red-barbarian

healthy

I
Igor Emelyanov, 2018-08-09
@MAGISTR_BRU

I recommend viewing an article directly from one of the RecyclreView developers - https://proandroiddev.com/recyclerview-pro-tips-pa...
The answer to your question is point 2 in the article.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question