title: OnBindViewHolder: why sometimes position don't start from zero?
body: <p>I'm using a RecyclerView and I noticed a strange behavior: I put a log every time <code>onBindViewHolder()</code> is called logging the actual position and sometimes the position don't start from zero, do you know why? For me this is a problem cause in position 0 I have a different logic.</p>
  <p>That's the logger:</p>
  <pre><code>2022-02-15 16:19:51.833 D/UpdateFragment: &gt;&gt;&gt;ViewModel.GetAllCards()
  2022-02-15 16:19:51.834 D/UpdateFragment: &gt;&gt;&gt;ViewModel.GetAllTags()
  2022-02-15 16:19:51.864 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position:0
  2022-02-15 16:19:52.110 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position:1
  2022-02-15 16:19:52.266 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position:2
  2022-02-15 16:19:52.331 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position:3
  2022-02-15 16:20:03.696 D/UpdateFragment: &gt;&gt;&gt;ViewModel.GetAllCards()
  2022-02-15 16:20:03.722 D/UpdateFragment: &gt;&gt;&gt;ViewModel.GetAllCards()
  2022-02-15 16:20:03.729 D/UpdateFragment: &gt;&gt;&gt;ViewModel.GetAllCards()
  2022-02-15 16:20:03.729 D/UpdateFragment: &gt;&gt;&gt;ViewModel.GetAllCards()
  2022-02-15 16:20:03.730 D/UpdateFragment: &gt;&gt;&gt;ViewModel.GetAllCards()
  2022-02-15 16:20:03.737 D/UpdateFragment: &gt;&gt;&gt;ViewModel.GetAllCards()
  2022-02-15 16:20:03.743 D/UpdateFragment: &gt;&gt;&gt;ViewModel.GetAllCards()
  2022-02-15 16:20:03.750 D/UpdateFragment: &gt;&gt;&gt;ViewModel.GetAllCards()
  2022-02-15 16:20:03.761 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position:2
  2022-02-15 16:20:03.830 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position:3
  2022-02-15 16:20:03.891 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position:1
  2022-02-15 16:20:04.042 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position:0
  </code></pre>
  <p>Ok, I understand the order isn't always the same, but in my app, when I update data I notice that there is a mysterious swap between 2 ViewHolder's layout, but in my code I never assign a layout to the ViewHolder. As you can see in the log the id of the layout associated with the position changes.</p>
  <pre><code>2022-02-15 19:03:10.878 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position[0]android.widget.LinearLayout{83f4271 G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
  2022-02-15 19:03:11.593 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position[1]android.widget.LinearLayout{e951d5e G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
  2022-02-15 19:03:11.954 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position[2]android.widget.LinearLayout{61b8127 G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
  2022-02-15 19:03:18.326 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;View android.widget.LinearLayout{61b8127 V.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}true
  2022-02-15 19:03:18.953 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;View androidx.constraintlayout.widget.ConstraintLayout{8510217 V.E...... ......I. 0,0-0,0 #7f08021e app:id/layout_update_card}true
  2022-02-15 19:03:53.394 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Saved
  2022-02-15 19:03:53.582 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position[2]android.widget.LinearLayout{83f4271 G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
  2022-02-15 19:03:53.729 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position[1]android.widget.LinearLayout{e951d5e G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
  2022-02-15 19:03:54.005 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position[0]android.widget.LinearLayout{61b8127 V.E...... .......D 0,98-720,761 #7f0800f5 app:id/layout_cards}
  2022-02-15 19:03:54.437 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position[0]android.widget.LinearLayout{61b8127 V.E...... .......D 0,98-720,378 #7f0800f5 app:id/layout_cards}
  2022-02-15 19:03:54.695 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position[1]android.widget.LinearLayout{e951d5e G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
  2022-02-15 19:03:54.879 D/RecyclerViewAdapterUpdate: &gt;&gt;&gt;Position[2]android.widget.LinearLayout{83f4271 G.E...... ......I. 0,0-0,0 #7f0800f5 app:id/layout_cards}
  
  </code></pre>
  <pre><code>public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
  
          Log.d(TAG, &quot;&gt;&gt;&gt;Position[&quot;+position+&quot;]&quot; + holder.linearLayout);
          if (position == 0) {
  
              // All the cards
              holder.numberOfItems.setText(String.valueOf(cardList.size()));
              holder.tagName.setText(R.string.all_cards_tag);
              holder.clearTag.setVisibility(View.GONE); // Can't delete all cards
              holder.checkBox.setChecked(allCardIsChecked);
              holder.checkBox.setOnClickListener(view -&gt; {
  
                  SharedPreferences.Editor editor = sharedPreferences.edit();
                  editor.putInt(Utilities.RECYCLER_CARD_POSITION, 0);
                  editor.putBoolean(Utilities.SHOULD_SHUFFLE, true);
  
                  if (holder.checkBox.isChecked()) {
  
                      MainActivity.recyclerTagList.clear();
                      editor.putStringSet(Utilities.SELECTED_TAGS, new HashSet&lt;&gt;());
                      Log.d(TAG, &quot;&gt;&gt;Tags selected: &quot; + MainActivity.recyclerTagList);
  
                      numberOfSelected = 1;
                      if (!allCardIsChecked) {
                          allCardIsChecked = true;
                          notifyDataSetChanged();
                      }
  
                  } else {
                      // Can't deselect all cards, at least one group chosen
                      holder.checkBox.setChecked(true);
                      Toast.makeText(context, R.string.min_one_tag, Toast.LENGTH_SHORT).show();
                  }
  
                  editor.commit();
  
              });
  
              initializeLayoutCards(cardList,null,  holder, true);
  
          } else {
  
              // Single TAG after all cards
              Tag tag = tagList.get(position - 1);
  
              List&lt;CardWithTags&gt; listOfSingleTag = new ArrayList&lt;&gt;();
              for (CardWithTags cwt: cardList) {
                  for (Tag t: cwt.getTagList()) {
                      if (t.getTag().equals(tag.getTag()))
                          listOfSingleTag.add(cwt);
                  }
              }
  
              initializeLayoutCards(listOfSingleTag, tag, holder, false);
  
              holder.numberOfItems.setText(String.valueOf(listOfSingleTag.size()));
              holder.tagName.setText(tag.getTag());
              holder.clearTag.setVisibility(View.VISIBLE);
              if (allCardIsChecked)
                  holder.checkBox.setChecked(false);
              else {
                  holder.checkBox.setChecked(false);
                  for (String s: selectedTags) {
                      if (s.equalsIgnoreCase(tag.getTag()))
                          holder.checkBox.setChecked(true);
                  }
              }
              holder.checkBox.setOnClickListener(view -&gt; {
  
                  SharedPreferences.Editor editor = sharedPreferences.edit();
                  editor.putInt(Utilities.RECYCLER_CARD_POSITION, 0);
                  editor.putBoolean(Utilities.SHOULD_SHUFFLE, true);
  
                  if (holder.checkBox.isChecked()) {
                      MainActivity.recyclerTagList.add(tag);
                      selectedTags = sharedPreferences.getStringSet(Utilities.SELECTED_TAGS, new HashSet&lt;&gt;());
                      selectedTags.add(tag.getTag());
                      editor.putStringSet(Utilities.SELECTED_TAGS, selectedTags);
                      Log.d(TAG, &quot;&gt;&gt;Tags selected: &quot; + MainActivity.recyclerTagList);
  
                      if (allCardIsChecked) {
                          allCardIsChecked = false;
                          notifyDataSetChanged();
                      } else {
                          ++numberOfSelected;
                      }
                  } else {
                      if (numberOfSelected == 1) {
                          Toast.makeText(context, R.string.min_one_tag, Toast.LENGTH_SHORT).show();
                          holder.checkBox.setChecked(true);
                      }
                      else {
                          --numberOfSelected;
                          MainActivity.recyclerTagList.removeIf(t -&gt; t.getTag().equalsIgnoreCase(tag.getTag()));
                          selectedTags = sharedPreferences.getStringSet(Utilities.SELECTED_TAGS, new HashSet&lt;&gt;());
                          selectedTags.remove(tag.getTag());
                          editor.putStringSet(Utilities.SELECTED_TAGS, selectedTags);
                          Log.d(TAG, &quot;&gt;&gt;Tags selected: &quot; + MainActivity.recyclerTagList);
                      }
                  }
  
                  editor.commit();
  
              });
  
              View viewDialogTag = LayoutInflater.from(context).inflate(R.layout.dialog_modify_tag, (ViewGroup) null);
              EditText tagNameEditText = viewDialogTag.findViewById(R.id.tag_name_dialog);
              tagNameEditText.setText(tag.getTag());
  
              // In this way the dialog is created only one time
              AlertDialog dialogTag = getDialogUpdateTag(tag, viewDialogTag, tagNameEditText);
              AlertDialog dialogDeleteTag = getDialogDeleteTag(tag);
  
              holder.tagName.setOnLongClickListener( view -&gt; {
                  // Change tag name only if closed
                  if (holder.linearLayout.getVisibility() == View.GONE)
                      dialogTag.show();
                  return true;
              });
  
              holder.clearTag.setOnClickListener( view -&gt; dialogDeleteTag.show());
  
          }
  
      }
  
  private void initializeLayoutCards(List&lt;CardWithTags&gt; cardList, Tag tag, ViewHolder holder, boolean isAllCards) {
  
          // Or it will add already added cards
          holder.linearLayout.removeAllViews();
  
          for (CardWithTags cwt : cardList) {
  
              Card card = cwt.getCard();
  
              View cardView = LayoutInflater.from(context).inflate(R.layout.card_update, holder.linearLayout, false);
              TextView textViewCardName = cardView.findViewById(R.id.card_name);
              Button clearButton = cardView.findViewById(R.id.clear_card);
              ConstraintLayout layoutCardUpdate = cardView.findViewById(R.id.layout_update_card);
              EditText titleEditText = cardView.findViewById(R.id.update_title_edit_text);
              EditText taboo1EditText = cardView.findViewById(R.id.update_taboo_1_edit_text);
              EditText taboo2EditText = cardView.findViewById(R.id.update_taboo_2_edit_text);
              EditText taboo3EditText = cardView.findViewById(R.id.update_taboo_3_edit_text);
              EditText taboo4EditText = cardView.findViewById(R.id.update_taboo_4_edit_text);
              EditText taboo5EditText = cardView.findViewById(R.id.update_taboo_5_edit_text);
              Button saveButton = cardView.findViewById(R.id.save_button);
              Button tagButton = cardView.findViewById(R.id.tag_button);
  
              textViewCardName.setText(card.getTitle());
              titleEditText.setText(card.getTitle());
              taboo1EditText.setText(card.getTabooWord1());
              taboo2EditText.setText(card.getTabooWord2());
              taboo3EditText.setText(card.getTabooWord3());
              taboo4EditText.setText(card.getTabooWord4());
              taboo5EditText.setText(card.getTabooWord5());
  
              saveButton.setOnClickListener(view -&gt; {
  
                  Animations.doReduceIncreaseAnimation(view);
  
                  String title = titleEditText.getText().toString();
                  String taboo1 = taboo1EditText.getText().toString();
                  String taboo2 = taboo2EditText.getText().toString();
                  String taboo3 = taboo3EditText.getText().toString();
                  String taboo4 = taboo4EditText.getText().toString();
                  String taboo5 = taboo5EditText.getText().toString();
  
                  if (title.equalsIgnoreCase(card.getTitle()) &amp;&amp;
                      taboo1.equalsIgnoreCase(card.getTabooWord1()) &amp;&amp;
                      taboo2.equalsIgnoreCase(card.getTabooWord2()) &amp;&amp;
                      taboo3.equalsIgnoreCase(card.getTabooWord3()) &amp;&amp;
                      taboo4.equalsIgnoreCase(card.getTabooWord4()) &amp;&amp;
                      taboo5.equalsIgnoreCase(card.getTabooWord5())) {
                      Log.d(TAG, &quot;&gt;&gt;Change something before saving card&quot;);
                      return;
                  }
  
                  Card newCard = new Card(title, taboo1, taboo2, taboo3, taboo4, taboo5);
                  newCard.setIdCard(card.getIdCard());
  
                  // Check if new title already exists
                  for (CardWithTags c: this.cardList) {
                      if (!c.getCard().getTitle().equalsIgnoreCase(card.getTitle()) &amp;&amp; c.getCard().getTitle().equalsIgnoreCase(title)) {
                          Toast.makeText(context, R.string.title_already_exists, Toast.LENGTH_SHORT).show();
                          return;
                      }
                  }
  
                  cwt.setCard(newCard);
                  Log.d(TAG, &quot;&gt;&gt;New cwt: &quot; + cwt);
                  Log.d(TAG, &quot;&gt;&gt;&gt;Saved&quot;);
                  viewModelFragment.updateCWT(cwt);
                  Toast.makeText(context, R.string.card_updated, Toast.LENGTH_SHORT).show();
              });
  
              tagButton.setOnClickListener(view -&gt; {
  
                  Animations.doReduceIncreaseAnimation(view);
              });
  
              textViewCardName.setOnClickListener(view -&gt; {
                  openCloseView(layoutCardUpdate);
              });
  
              AlertDialog dialogDeleteCard;
              if (!isAllCards)
                  dialogDeleteCard = getDialogDeleteCardOrTag(card, tag);
              else
                  dialogDeleteCard = getDialogDeleteCard(card);
  
              clearButton.setOnClickListener(view -&gt; dialogDeleteCard.show());
  
              // Set the click on both number of items and tag name
              holder.tagName.setOnClickListener(view -&gt; {
                  openCloseView(holder.linearLayout);
              });
              holder.numberOfItems.setOnClickListener(view -&gt; {
                  openCloseView(holder.linearLayout);
              });
  
              holder.linearLayout.addView(cardView);
  
          }
  
      }
  
      private void openCloseView(View view) {
  
          if (view.getVisibility() == View.GONE) {
  
              view.setVisibility(View.VISIBLE);
              boolean isVisible = view.getVisibility() == View.VISIBLE? true : false;
              Log.d(TAG, &quot;&gt;&gt;&gt;View &quot; + view +isVisible);
  
              AnimationSet animation = new AnimationSet(true);
              Animation animationAlpha = new AlphaAnimation(0, 1);
              animation.addAnimation(animationAlpha);
              Animation animationTranslate = new TranslateAnimation(0, 0, -view.getHeight(), 0);
              animation.addAnimation(animationTranslate);
              Animation animationY = new ScaleAnimation(1, 1, 0, 1);
              animationY.setInterpolator(new LinearInterpolator());
              animation.addAnimation(animationY);
              animation.setDuration(200);
  
              view.startAnimation(animation);
  
          } else {
  
              AnimationSet animation = new AnimationSet(true);
              Animation animationAlpha = new AlphaAnimation(1, 0);
              animation.addAnimation(animationAlpha);
              Animation animationTranslate = new TranslateAnimation(0, 0, 0, -view.getHeight());
              animation.addAnimation(animationTranslate);
              Animation animationY = new ScaleAnimation(1, 1, 1, 0);
              animationY.setInterpolator(new LinearInterpolator());
              animation.addAnimation(animationY);
              animation.setDuration(200);
  
              animation.setAnimationListener(new Animation.AnimationListener() {
                  @Override
                  public void onAnimationStart(Animation animation) {
  
                  }
  
                  @Override
                  public void onAnimationEnd(Animation animation) {
                      view.setVisibility(View.GONE);
                      boolean isVisible = view.getVisibility() == View.VISIBLE;
                      Log.d(TAG, &quot;&gt;&gt;&gt;View &quot; + view +isVisible);
                  }
  
                  @Override
                  public void onAnimationRepeat(Animation animation) {
  
                  }
              });
  
              view.startAnimation(animation);
          }
      }
  </code></pre>