title: RecyclerView selects multiple items on a item click
body: <p>I have implemented a <code>RecyclerView</code> to display a list of Contacts (200 approximately). A user can select multiple items. The selection make visible a tick to indicate to the user the selected contacts. However, when the user select a item, the tick appears on several non-selected items. The frequency of occurrence is the same.</p>
  <p>Could you tell me what I am doing wrong. Thanks !</p>
  <p>Here is my implementation :</p>
  <p>I have an activity called NewAppointmentActivity which contains a fragment called NewAppointmentPhoneContactsFragment. This fragment is a RecyclerView :</p>
  <p><strong>File fragment_new_appointment_phone_contacts.xml</strong></p>
  <pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
  &lt;androidx.recyclerview.widget.RecyclerView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
      xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
      xmlns:tools=&quot;http://schemas.android.com/tools&quot;
      android:id=&quot;@+id/list&quot;
      android:name=&quot;com.example.geoappointment.fragments.NewAppointmentPhoneContactsFragment&quot;
      android:layout_width=&quot;match_parent&quot;
      android:layout_height=&quot;match_parent&quot;
      android:layout_marginLeft=&quot;16dp&quot;
      android:layout_marginRight=&quot;16dp&quot;
      app:layoutManager=&quot;LinearLayoutManager&quot;
      tools:context=&quot;.fragments.NewAppointmentPhoneContactsFragment&quot;
      tools:listitem=&quot;@layout/fragment_contact_item&quot; /&gt;
  </code></pre>
  <p><strong>File NewAppointmentPhoneContactsFragment.java</strong></p>
  <pre><code>public class NewAppointmentPhoneContactsFragment extends Fragment {
      private static final String TAG = &quot;NewAppointmentPhoneCont&quot;;
  
      private NewAppointmentActivityViewModel viewModel;
  
      public NewAppointmentPhoneContactsFragment() {}
  
      @Override
      public void onCreate(@Nullable Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
  
          viewModel = new ViewModelProvider(this).get(NewAppointmentActivityViewModel.class);
  
          new LoadContactsFromPhoneAsyncTask(
                  requireActivity().getContentResolver(),
                  requireActivity().getApplicationContext(),
                  new AsyncTaskCallback&lt;ArrayList&lt;Contact&gt;&gt;() {
                      @Override
                      public void onPostExecuteCallback(ArrayList&lt;Contact&gt; param) {
                          if (viewModel != null) {
                              viewModel.setPhoneContacts(param);
                          }
                      }
                  }).execute();
      }
  
      @Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
          View view = inflater.inflate(R.layout.fragment_new_appointment_phone_contacts, container, false);
  
          if (view instanceof RecyclerView) {
              Context context = view.getContext();
              RecyclerView recyclerView = (RecyclerView) view;
              recyclerView.setLayoutManager(new LinearLayoutManager(context));
              
              viewModel.getPhoneContacts().observe(getViewLifecycleOwner(), contacts -&gt; {
                  recyclerView.setAdapter(new MyContactListRecyclerViewAdapter(contacts));
              });
          }
  
          return view;
      }
  }
  </code></pre>
  <p>When the AsynTask is done, it notifies the model which sets the adapter to the RecyclerView (it works fine).</p>
  <p><strong>File MyContactListRecyclerViewAdapter.java</strong></p>
  <pre><code>public class MyContactListRecyclerViewAdapter extends RecyclerView.Adapter&lt;MyContactListRecyclerViewAdapter.ViewHolder&gt; {
      private static final String TAG = &quot;MyContactListRecyclerVi&quot;;
  
      private final ArrayList&lt;Contact&gt; mValues;
      private final ArrayList&lt;Contact&gt; mSelectedValues;
  
      public MyContactListRecyclerViewAdapter(ArrayList&lt;Contact&gt; items) {
          mValues = items;
          mSelectedValues = new ArrayList&lt;&gt;();
      }
  
      @NotNull
      @Override
      public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
          View view = LayoutInflater
                  .from(parent.getContext())
                  .inflate(R.layout.fragment_contact_item, parent, false);
          return new ViewHolder(view);
      }
  
      @Override
      public void onBindViewHolder(final ViewHolder holder, int position) {
          holder.mItem = mValues.get(position);
          holder.mNameTextView.setText(holder.mItem.getName());
          holder.mPhoneNumberView.setText(holder.mItem.getPhoneNumber());
  
          if (mSelectedValues.contains(holder.mItem)) {
              holder.tickImageView.setVisibility(View.VISIBLE);
          }
  
          holder.mView.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  onItemClick(holder, position);
              }
          });
      }
  
      @Override
      public int getItemCount() {
          return mValues.size();
      }
  
      public void onItemClick(final ViewHolder holder, int position) {
          // Récupération du contact sélectionné
          final Contact contact = mValues.get(position);
          Log.d(TAG, contact.toString());
  
          // Si le contact n'est pas nul
          if (contact != null) {
              // Si le contact n'est pas déjà sélectionné
              if (!mSelectedValues.contains(contact)) {
                  // Ajout du contact dans la liste des contacts sélectionnés
                  mSelectedValues.add(contact);
  
                  // Démasque la tick de sélection
                  holder.tickImageView.setVisibility(View.VISIBLE);
              } else {
                  // Retire le contact de la liste des contacts sélectionnés
                  mSelectedValues.remove(contact);
  
                  // Masque la tick de sélection
                  holder.tickImageView.setVisibility(View.INVISIBLE);
              }
          }
  
          Log.d(TAG, mSelectedValues.toString());
      }
  
      public class ViewHolder extends RecyclerView.ViewHolder {
          public final View mView;
          public final TextView mNameTextView;
          public final TextView mPhoneNumberView;
          public final ImageView tickImageView;
          public Contact mItem;
  
          public ViewHolder(View view) {
              super(view);
              mView = view;
              mNameTextView = (TextView) view.findViewById(R.id.contactItemNameTextView);
              mPhoneNumberView = (TextView) view.findViewById(R.id.contactItemPhoneNumber);
              tickImageView = (ImageView) view.findViewById(R.id.contactItemTickImageView);
  
              if (mItem != null) {
                  if (mSelectedValues.contains(mItem)) {
                      tickImageView.setVisibility(View.VISIBLE);
                  }
              }
          }
      }
  }
  </code></pre>