Dioptre Pic
Dioptre Pic

Reputation: 153

RecyclerView onClick gives wrong item

I have a RecyclerView that shows a list of student details. The issue I face is when I click on the first item it returns the data of the second item. I believe that it has something to do with getAdapterPosition(), but I'm not sure.

In this case, it returns the Roll No. of the second student(item) when the first student is selected.

Any help is appreciated


RecyclerViewAdapter

public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.ViewHolder> {
    Context context;
    public List<StudentDataModel> dataModels;
    public StudentDataModel dataAdapter;

    public StudentAdapter(List<StudentDataModel> getDataAdapter, Context context){
        super();
        this.dataModels = getDataAdapter;
        this.context = context;
    }

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

    @Override
    public void onBindViewHolder(final StudentAdapter.ViewHolder viewHolder, final int position) {
        dataAdapter =  dataModels.get(position);        
        viewHolder.NameStudentCard.setText(dataAdapter.getName());
        viewHolder.RankStudentCard.setText(dataAdapter.getRank());
        viewHolder.RollStudentCard.setText(dataAdapter.getRoll());

        viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                notifyDataSetChanged();                
                Toast.makeText(v.getContext(), "Tapped on" + dataAdapter.getRoll(), Toast.LENGTH_SHORT).show(); //Here it returns the Roll No. of the second student(item) in the recyclerView.                
                Intent intent = new Intent (v.getContext(), StudentDetailsActivity.class);                
                v.getContext().startActivity(intent);
            }
        });

    }

    class ViewHolder extends RecyclerView.ViewHolder{
        public TextView NameStudentCard;
        public TextView RankStudentCard;
        public TextView RollStudentCard;

        public ViewHolder(View itemView) {
            super(itemView);
            NameStudentCard=(TextView)itemView.findViewById(R.id.textViewName);
            RankStudentCard=(TextView)itemView.findViewById(R.id.textViewRank);
            RollStudentCard =(TextView)itemView.findViewById(R.id.textViewEmployeeID);

        }
    }

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

}

Upvotes: 1

Views: 1393

Answers (3)

NehaK
NehaK

Reputation: 2727

Yes, because you are declaring object as global object. So it is getting update with last visible row's object, because onBindViewHolder() gets called for each visible row sequentially. So it will work properly only for last visible row.

So you need to declare it inside method :

comment this :

   // public StudentDataModel dataAdapter;

declare it here :

@Override
public void onBindViewHolder(final StudentAdapter.ViewHolder viewHolder, final int position) {

   final StudentDataModel dataAdapter =  dataModels.get(position); // add this here

}

Upvotes: 6

user4571931
user4571931

Reputation:

Try this code.. make interface into adapter class for click handling like this way..

 onItemClickListner onItemClickListner;

public void setOnItemClickListner(RecyclerViewAdpater.onItemClickListner onItemClickListner) {
    this.onItemClickListner = onItemClickListner;
}

 public interface onItemClickListner{
    void onItemClick(String data); // pass any data;
}


@Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
    // below code handle click event on recycler view item.
    String data=mStringList.get(position);
    holder.textView.setText(data);
    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            onItemClickListner.onItemClick(data); //pass your data;
        }
    });
}

after that bind adapter into recyclerview and adapter not null then called below code..

    recyclerViewAdpater.setOnItemClickListner(new RecyclerViewAdpater.onItemClickListner() {
        @Override
        public void onItemClick(String data) {
            // perform your operation.
            recyclerViewAdpater.notifyDataSetChanged();
        }
    });

Upvotes: 1

Basil jose
Basil jose

Reputation: 780

public class StudentAdapter extends RecyclerView.Adapter<StudentAdapter.ViewHolder> {

Context context;

public List<StudentDataModel> dataModels;


public StudentAdapter(List<StudentDataModel> getDataAdapter, Context context){

super();

this.dataModels = getDataAdapter;
this.context = context;
}

public StudentDataModel dataAdapter;


@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.student, parent, false);

    ViewHolder viewHolder = new ViewHolder(view);

    return viewHolder;

}

@Override
public void onBindViewHolder(final StudentAdapter.ViewHolder viewHolder, final int position) {

     dataAdapter =  dataModels.get(position);

    viewHolder.NameStudentCard.setText(dataAdapter.getName());

    viewHolder.RankStudentCard.setText(dataAdapter.getRank());

    viewHolder.RollStudentCard.setText(dataAdapter.getRoll());




}




@Override
public int getItemCount() {

    return dataModels.size();
}


class ViewHolder extends RecyclerView.ViewHolder{

    public TextView NameStudentCard;
    public TextView RankStudentCard;
    public TextView RollStudentCard;

    public ViewHolder(View itemView) {

        super(itemView);

        NameStudentCard=(TextView)itemView.findViewById(R.id.textViewName);
        RankStudentCard=(TextView)itemView.findViewById(R.id.textViewRank);
        RollStudentCard =(TextView)itemView.findViewById(R.id.textViewEmployeeID);

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

                Toast.makeText(v.getContext(), "Tapped on" + dataModels.get(getAdapterPosition()).getRoll(), Toast.LENGTH_SHORT).show(); 

                Intent intent = new Intent (v.getContext(), StudentDetailsActivity.class);

                v.getContext().startActivity(intent);
            }
        });

    }
}

}

Upvotes: 1

Related Questions