javaandroidclicklistener

Click listener inside OnBindViewHolder


I have the following code for the recyclerview adapter for an android app that I'm working on right now:

 @Override
public void onBindViewHolder(final FeedViewHolder contactViewHolder, final int i) {

    final FeedInfo ci = feedInfoList.get(i);

    //Set the text of the feed with your data
    contactViewHolder.feedText.setText(ci.getFeed());
    contactViewHolder.surNameText.setText(ci.getSurName());
    contactViewHolder.nameText.setText(ci.getFirstName());
    contactViewHolder.feedDate.setText(ci.getDate());
    contactViewHolder.numberOfGoingText.setText(ci.getNumber_of_going());
    contactViewHolder.numberOfInterestedText.setText(ci.getNumber_of_interested());

    //seteaza fotografia de profil in postare
    new ProfilePictureDownloadImage(contactViewHolder.profilePicture).execute(ci.getProfileImageURL());

    ImageButton interestedButton = contactViewHolder.interestedButton;
    interestedButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int position = i;
            FeedInfo fi = feedInfoList.get(position);
            int displayedNumberOfInterested = Integer.parseInt(ci.getNumber_of_interested()) + 1;
            contactViewHolder.numberOfInterestedText.setText(Integer.toString(displayedNumberOfInterested));
            System.out.println("emilutzy interested from within" + fi.getPostID());
            contactViewHolder.surNameText.setText("kk");
        }
    });
}

The problem is the click listener. In theory the button I press should increment the number right next to it. However, since I have to declare onBindViewHolder's arguments as final, only the first click works, the rest of the clicks do not change the value of the number. I am new to Android, so could you please help me find a better solution?


Solution

  • There's a nice method called getAdapterPosition() that you can use in your RecyclerView's ViewHolder.

    Instead of setting the click listener in onBindViewHolder, set it in the constructor of your ViewHolder like so:

    public class FeedViewHolder extends RecyclerView.ViewHolder {
        private TextView feedText;
        private TextView surNameText;
        private Button interestedButton;
        // ... the rest of your viewholder elements
    
        public FeedViewHolder(View itemView) {
            super(itemView);
    
            feedtext = itemView.findViewById(R.id.feedtext);
            // ... find your other views
    
            interestedButton.setOnClickListener(new View.OnClickListener() {
                final FeedInfo fi = feedInfoList.get(getAdapterPosition());
                int numInterested = Integer.parseInt(ci.getNumber_of_interested()) + 1;
    
                // setting the views here might work, 
                // but you will find that they reset themselves
                // after you scroll up and down (views get recycled).
    
                // find a way to update feedInfoList, 
                // I like to use EventBus to send an event to the
                // host activity/fragment like so:
                EventBus.getDefault().post(
                    new UpdateFeedInfoListEvent(getAdapterPosition(), numInterested));
    
                // in your host activity/fragment, 
                // update the list and call 
                // notifyDatasetChanged/notifyDataUpdated() 
                //on this RecyclerView adapter accordingly
            });
        }
    }
    

    Don't set your position in onBindViewHolder to final (Android Studio will warn you why).