title: Updating Heterogeneous RecyclerView with DiffUtil - Android
body: <p>UPDATED QUESTION:</p>
  
  <p>I have a RecyclerView with Heterogenous Items (RecyclerView holding items of two view types). I want to update this RecyclerView with the new data that I receive from API.</p>
  
  <p>All the examples and implementations show DiffUtil for updating RecyclerView containing items of a single view type.</p>
  
  <p>I am a beginner in Android and tried the following code -    </p>
  
  <pre><code>public class TestDiffCallback extends DiffUtil.Callback {
      private final List&lt;Object&gt; oldList;
      private final List&lt;Object&gt; newList;
  
      public TestDiffCallback(List&lt;Object&gt; oldList, List&lt;Object&gt; newList) {
          this.oldList = oldList;
          this.newList= newList;
      }
  
      @Override
      public int getOldListSize() {
          return oldList.size();
      }
  
      @Override
      public int getNewListSize() {
          return newList.size();
      }
  
      @Override
      public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
          if (oldList.get(oldItemPosition) instanceof ViewType1) {
              return (((ViewType1) oldList.get(oldItemPosition)).getUniqueID())
                      .equals(((ViewType1) newList.get(newItemPosition)).getUniqueID());
          } else if (oldList.get(oldItemPosition) instanceof ViewType2) {
              return (((ViewType2) oldList.get(oldItemPosition)).getUniqueID())
                      .equals(((ViewType2) newList.get(newItemPosition)).getUniqueID());
          }
          return false;
      }
  
      @Override
      public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
          if (oldList.get(oldItemPosition) instanceof ViewType1) {
              final ViewType1 oldViewType1 = (ViewType1) oldList.get(oldItemPosition);
              final ViewType1 newViewType1 = (ViewType1) oldList.get(newItemPosition);
  
              return (
                      oldViewType1.getUniqueID().equals(newViewType1.getUniqueID())
              );
          } else if (oldList.get(oldItemPosition) instanceof ViewType2) {
              final ViewType2 oldViewType2 = (ViewType2) oldList.get(oldItemPosition);
              final ViewType2 newViewType2 = (ViewType2) oldList.get(newItemPosition);
  
              return (
                      oldViewType2.getUniqueID().equals(newViewType2.getUniqueID())
              );
  
          }
          return false;
      }
  
      @Nullable
      @Override
      public Object getChangePayload(int oldItemPosition, int newItemPosition) {
          return super.getChangePayload(oldItemPosition, newItemPosition);
      }
  }
  </code></pre>
  
  <p>In my Heterogenous View Adapter I have this - </p>
  
  <pre><code>public void updateHomeItems(List&lt;Object&gt; testItems) {
      final TestDiffCallback diffCallback =
              new TestDiffCallback(this.testItems, testItems);
      final DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(diffCallback);
  
      this.testItems.clear();
      this.testItems.addAll(testItems);
      diffResult.dispatchUpdatesTo(this);
  }
  </code></pre>
  
  <p>and from my Fragment Class I fetch data from API and pass it to DiffUtil as follows-</p>
  
  <pre><code>programAdapter.updateHomeItems(refreshedTestItemsList);
  </code></pre>
  
  <p>This is the error that I get all the time -</p>
  
  <pre><code>E/AndroidRuntime: FATAL EXCEPTION: main
                       Process: com.acadnion, PID: 28315
                       io.reactivex.exceptions.UndeliverableException: java.lang.ClassCastException: com.acadnion.models.ViewType2 cannot be cast to com.acadnion.models.ViewType1
                       at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:366)
                       at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:111)
                       at android.os.Handler.handleCallback(Handler.java:751)
                       at android.os.Handler.dispatchMessage(Handler.java:95)
                       at android.os.Looper.loop(Looper.java:154)
                       at android.app.ActivityThread.main(ActivityThread.java:6186)
                       at java.lang.reflect.Method.invoke(Native Method)
                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
                       Caused by: java.lang.ClassCastException: com.acadnion.models.ViewType2 cannot be cast to com.acadnion.models.ViewType1
                       at com.acadnion.utils.TestDiffCallback.areItemsTheSame(TestDiffCallback.java:36)
                       at android.support.v7.util.DiffUtil.diffPartial(DiffUtil.java:224)
                       at android.support.v7.util.DiffUtil.calculateDiff(DiffUtil.java:136)
                       at android.support.v7.util.DiffUtil.calculateDiff(DiffUtil.java:97)
                       at com.acadnion.adapters.ProgramAdapter.updateHomeItems(ProgramAdapter.java:160)
                       at com.acadnion.fragments.TestFragment.addFetchedDataToList(TestFragment.java:182)
                       at com.acadnion.fragments.TestFragment.access$100(TestFragment.java:45)
                       at com.acadnion.fragments.TestFragment$3.onNext(TestFragment.java:153)
                       at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.drainNormal(ObservableObserveOn.java:200)
                       at io.reactivex.internal.operators.observable.ObservableObserveOn$ObserveOnObserver.run(ObservableObserveOn.java:252)
                       at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:109)
                       at android.os.Handler.handleCallback(Handler.java:751) 
                       at android.os.Handler.dispatchMessage(Handler.java:95) 
                       at android.os.Looper.loop(Looper.java:154) 
                       at android.app.ActivityThread.main(ActivityThread.java:6186) 
                       at java.lang.reflect.Method.invoke(Native Method) 
                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889) 
                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) 
  </code></pre>