title: RecyclerView item selection is throwing error
body: <p>I tried to implement the item selection feature in <em>RecyclerView</em> with the help of <em>SelectionTracker</em> but getting <em>IllegalArgumentException</em> and the stacktrace is not intuitive as it only shows the metadata.</p>
  
  <p><em>this is how I am building the tracker</em>  </p>
  
  <pre><code>wordAdapter.tracker = new SelectionTracker.Builder&lt;Long&gt;(
                  "mySelectionId",
                  recyclerView,
                  new StableIdKeyProvider(recyclerView),
                  new MyDetailsLookUp(recyclerView),
                  StorageStrategy.createLongStorage()
          ).withSelectionPredicate(
                  SelectionPredicates.&lt;Long&gt;createSelectAnything()
          ).build();
  </code></pre>
  
  <p><em>MyDetailsLookUp</em> class</p>
  
  <pre><code>class MyDetailsLookUp extends ItemDetailsLookup&lt;Long&gt; {
          RecyclerView recyclerView;
  
          MyDetailsLookUp(RecyclerView recyclerView) {
              this.recyclerView = recyclerView;
          }
  
          @Nullable
          @Override
          public ItemDetails&lt;Long&gt; getItemDetails(@NonNull MotionEvent e) {
              View view = recyclerView.findChildViewUnder(e.getX(), e.getY());
              if (view != null) {
                  //  getting individual view holders
                  return ((WordAdapter.MyViewHolder) recyclerView.getChildViewHolder(view)).getItemDetails();
              }
              return null;
          }
      }
  </code></pre>
  
  <p><em>getItemDetails</em> method in <em>ViewHolder</em> in the <em>WordAdapter</em></p>
  
  <pre><code>ItemDetailsLookup.ItemDetails&lt;Long&gt; getItemDetails(){
              return new ItemDetailsLookup.ItemDetails&lt;Long&gt;(){
                  @Override
                  public int getPosition() {
                      return getAdapterPosition();
                  }
  
                  @Nullable
                  @Override
                  public Long getSelectionKey() {
                      return getItemId();
                  }
              };
          }
  </code></pre>
  
  <p><strong>Stacktrace 1</strong>  </p>
  
  <pre><code>java.lang.IllegalArgumentException
          at androidx.core.util.Preconditions.checkArgument(Preconditions.java:38)
          at androidx.recyclerview.selection.DefaultSelectionTracker.anchorRange(DefaultSelectionTracker.java:269)
          at androidx.recyclerview.selection.MotionInputHandler.selectItem(MotionInputHandler.java:60)
          at androidx.recyclerview.selection.TouchInputHandler.onLongPress(TouchInputHandler.java:132)
          at androidx.recyclerview.selection.GestureRouter.onLongPress(GestureRouter.java:96)
          at android.view.GestureDetector.dispatchLongPress(GestureDetector.java:778)
          at android.view.GestureDetector.-wrap0(Unknown Source:0)
          at android.view.GestureDetector$GestureHandler.handleMessage(GestureDetector.java:293)
          at android.os.Handler.dispatchMessage(Handler.java:105)
          at android.os.Looper.loop(Looper.java:164)
          at android.app.ActivityThread.main(ActivityThread.java:6541)
          at java.lang.reflect.Method.invoke(Native Method)
          at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
  </code></pre>
  
  <p>Surprisingly, I have implemented the same code in Kotlin and it is working fine there. I found a SO post with the similar problem <a href="https://stackoverflow.com/questions/52460141/cannot-change-whether-this-adapter-has-stable-ids-while-the-adapter-has-register">this</a>, the accepted answer suggesting a custom <em>ItemKeyProvider</em> to be passed instead of <em>StableIdKeyProvider</em>. Therefore, on doing so hit me with this error.</p>
  
  <p><strong>Stacktrace 2</strong>  </p>
  
  <pre><code>java.lang.IllegalStateException: Two different ViewHolders have the same stable ID. Stable IDs in your adapter MUST BE unique and SHOULD NOT change.
       ViewHolder 1:ViewHolder{987472c position=1 id=-1, oldPos=-1, pLpos:-1} 
       View Holder 2:ViewHolder{e50e5f5 position=2 id=-1, oldPos=-1, pLpos:-1 not recyclable(1)} androidx.recyclerview.widget.RecyclerView{617d73 VFED..... .F....ID 42,42-1038,1542 #7f08007b app:id/recyclerview}, adapter:com.example.roomwordssample.WordAdapter@7ada430, layout:androidx.recyclerview.widget.GridLayoutManager@a15b8a9, context:com.example.roomwordssample.Main2Activity@ca1d275
          at androidx.recyclerview.widget.RecyclerView.handleMissingPreInfoForChangeError(RecyclerView.java:4058)
          at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep3(RecyclerView.java:3982)
          at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3652)
          at androidx.recyclerview.widget.RecyclerView.consumePendingUpdateOperations(RecyclerView.java:1877)
          at androidx.recyclerview.widget.RecyclerView$1.run(RecyclerView.java:407)
          at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
          at android.view.Choreographer.doCallbacks(Choreographer.java:723)
          at android.view.Choreographer.doFrame(Choreographer.java:655)
          at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
          at android.os.Handler.handleCallback(Handler.java:789)
          at android.os.Handler.dispatchMessage(Handler.java:98)
          at android.os.Looper.loop(Looper.java:164)
          at android.app.ActivityThread.main(ActivityThread.java:6541)
          at java.lang.reflect.Method.invoke(Native Method)
          at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
  </code></pre>
  
  <p><em>updated tracker</em>  </p>
  
  <pre><code>wordAdapter.tracker = new SelectionTracker.Builder&lt;Long&gt;(
                  "mySelectionId",
                  recyclerView,
                 new GetItemDetails(recyclerView, ItemKeyProvider.SCOPE_MAPPED),
                  new MyDetailsLookUp(recyclerView),
                  StorageStrategy.createLongStorage()
          ).withSelectionPredicate(
                  SelectionPredicates.&lt;Long&gt;createSelectAnything()
          ).build();
  </code></pre>
  
  <p><em>CustomItemKeyProvider</em>  </p>
  
  <pre><code>class CustomItemKeyProvider extends ItemKeyProvider&lt;Long&gt; {
          RecyclerView recyclerView;
  
          CustomItemKeyProvider(RecyclerView recyclerView, int scope) {
              super(scope);
              this.recyclerView = recyclerView;
          }
  
          @Nullable
          @Override
          public Long getKey(int position) {
              return wordAdapter.getItemId(position);
          }
  
          @Override
          public int getPosition(@NonNull Long key) {
              RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForItemId(key);
              return viewHolder == null ? RecyclerView.NO_POSITION : viewHolder.getLayoutPosition();
          }
      }
  </code></pre>
  
  <p><em>P.S</em>: <code>wordAdapter.setHasStableIds(true)</code> is done before setting the adapter to the <code>RecyclerView</code></p>