title: Unexpected RecyclerView Scroll
body: <p>My recycler view auto scrolls a bit when new data is loaded, I've tried numerous solutions out there but nothing helped, pagination is setup with diffutil. setting <code>seHasFixedSize</code> to true also doesn't work
  the video might bring clarity to the question.
  <a href="https://photos.app.goo.gl/SSiyxGWkeqvaHRPj6" rel="nofollow noreferrer">https://photos.app.goo.gl/SSiyxGWkeqvaHRPj6</a></p>
  
  <p>Here's my Adapter code, also it's a multi-view adapter.</p>
  
  <pre><code>public class ChatAdapter extends PagedListAdapter&lt;ChatMessage, RecyclerView.ViewHolder&gt; {
  
      private static final String TAG = "ChatAdapter";
  
      private static final DiffUtil.ItemCallback&lt;ChatMessage&gt; DIFF_CALLBACK = new DiffUtil.ItemCallback&lt;ChatMessage&gt;() {
          @Override
          public boolean areItemsTheSame(@NonNull ChatMessage oldTopMoment, @NonNull ChatMessage newTopMoment) {
              // User properties may have changed if reloaded from the DB, but ID is fixed
              return oldTopMoment.getPk().equals(newTopMoment.getPk());
          }
  
          @Override
          public boolean areContentsTheSame(@NonNull ChatMessage oldTopMoment, @NonNull ChatMessage newTopMoment) {
              // NOTE: if you use equals, your object must properly override Object#equals() !!!
              // Incorrectly returning false here will result in too many animations.
              return oldTopMoment.equals(newTopMoment);
          }
      };
      private ArrayList&lt;String&gt; sameRegionStores;
      private boolean sendMessage;
      private ChatCallback chatCallback;
      private ErrorHandler errorHandler;
      private boolean isAllStoreSelect;
      private boolean isDetailsScreen;
      private NetworkState networkState;
      private ArrayList&lt;Store&gt; storesArrayList;
      private User user;
  
      ChatAdapter(boolean sendMessage, ChatCallback chatCallback, ErrorHandler errorHandler, boolean isAllStoreSelect) {
          super(DIFF_CALLBACK);
          this.sendMessage = sendMessage;
          this.chatCallback = chatCallback;
          this.errorHandler = errorHandler;
          this.isAllStoreSelect = isAllStoreSelect;
      }
  
      public static View inflate(@NonNull ViewGroup container, @LayoutRes int layoutResId) {
          return LayoutInflater.from(container.getContext()).inflate(layoutResId, container, false);
      }
  
      void setAllStoreSelect(boolean allStoreSelect, boolean isDetailsScreen) {
          isAllStoreSelect = allStoreSelect;
          this.isDetailsScreen = isDetailsScreen;
      }
  
      @Override
      @NonNull
      public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
          if (viewType == R.layout.chat_network_state_item) {
              return new ChatNetworkStateItemViewHolder(inflate(parent, R.layout.chat_network_state_item), errorHandler, chatCallback);
          } else if (viewType == ChatMessage.ChatType.dailyAchievements.ordinal() || viewType == ChatMessage.ChatType.storeAchievements.ordinal()) {
              return new TeamChatAchievementDelegate().onCreateViewHolder(parent, sendMessage, chatCallback);
          } else if (viewType == ChatMessage.ChatType.recognition.ordinal()) {
              return new TeamChatRecognitionDelegate().onCreateViewHolder(parent, sendMessage, chatCallback);
          } else if (viewType == ChatMessage.ChatType.message.ordinal()) {
              return new TeamChatDirectMessageDelegate().onCreateViewHolder(parent, sendMessage, chatCallback, isDetailsScreen);
          } else if (viewType == ChatMessage.ChatType.reply.ordinal()) {
              return new TeamChatReplyDelegate().onCreateViewHolder(parent, chatCallback, isAllStoreSelect, isDetailsScreen);
          } else {
              return new TeamChatBaseDelegate().onCreateViewHolder(parent);
          }
      }
  
      @Override
      public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
          if (getItemViewType(position) == R.layout.chat_network_state_item) {
  //            ((ChatNetworkStateItemViewHolder) holder).bind(networkState, getItemCount() - 1 == 0);
              ((ChatNetworkStateItemViewHolder) holder).bind(networkState);
          } else {
              ChatMessage chatMessage = getItem(position);
              if (chatMessage == null) {
                  return;
              }
  
              if (holder instanceof TeamChatBaseDelegate.TeamChatBaseViewHolder) {
                  chatMessage.setShowingStoreName(isAllStoreSelect);
                  if (storesArrayList != null) {
                      chatMessage.setStoreName(getStoreName(chatMessage));
                  }
                  ((TeamChatBaseDelegate.TeamChatBaseViewHolder) holder).bind(chatMessage);
              }
          }
      }
  
      private String getStoreName(ChatMessage chatMessage) {
          String[] storeIds = chatMessage.getStoreIds();
  
          if (storeIds == null) {
              return "N/A";
          }
  
          if (user.hasPrivilege(Role.PrivilegeLevel.company)) {
              for (Store store : storesArrayList) {
                  if (storeIds.length &gt; 1) {
                      List&lt;String&gt; aList = Arrays.asList(storeIds);
                      chatMessage.setStoreListForAggregation(aList);
                      Timber.d("%s Restaurants", storeIds.length);
                      return storeIds.length + " Restaurants";
                  }
                  if (store.id.equals(storeIds[0])) {
                      List&lt;String&gt; aList = Arrays.asList(storeIds);
                      chatMessage.setStoreListForAggregation(aList);
                      Timber.d(store.name);
                      return store.name;
                  }
              }
          } else if (user.isDivisionManager()) {
              String result = filterStoresIds(storeIds, user.store.divisionId, true);
              Timber.d(result);
              chatMessage.setStoreListForAggregation(sameRegionStores);
              return result;
          } else if (user.isMultiStoreManager()) {
              String res = filterStoresIds(storeIds, user.store.regionId, false);
              Timber.d(res);
              chatMessage.setStoreListForAggregation(sameRegionStores);
              return res;
  
          }
  
          return "N/A";
      }
  
      private String filterStoresIds(String[] storeIds, String id, boolean isDM) {
          ArrayList&lt;Store&gt; storeList = getSameRegionStores(id, storeIds, isDM);
          return storeList.size() == 1 ? storeList.get(0).name : storeList.size() + " Restaurants";
      }
  
      private ArrayList&lt;Store&gt; getSameRegionStores(String id, String[] storeIds, boolean isDM) {
          ArrayList&lt;Store&gt; arrayList = new ArrayList&lt;Store&gt;();
          sameRegionStores = new ArrayList&lt;&gt;();
  
          for (Store store : storesArrayList) {
              for (String storeId : storeIds) {
                  String idToCompare = "";
                  if (isDM) {
                      idToCompare = store.divisionId;
                  } else {
                      idToCompare = store.regionId;
                  }
                  if (store.id.equals(storeId) &amp;&amp; idToCompare.equals(id)) {
                      sameRegionStores.add(storeId);
                      arrayList.add(store);
                  }
              }
          }
          return arrayList;
      }
  
      @Override
      public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
          super.onViewRecycled(holder);
  
          if (holder instanceof TeamChatBaseDelegate.TeamChatBaseViewHolder) {
              ((TeamChatBaseDelegate.TeamChatBaseViewHolder) holder).unbind();
          }
      }
  
      @Override
      public int getItemViewType(int position) {
          if (hasExtraRow() &amp;&amp; position == getItemCount() - 1)  // i.e 0
              return R.layout.chat_network_state_item;
  
          ChatMessage chatMessage = getItem(position);
          if (chatMessage == null)
              return -1;
  
          return chatMessage.getType().ordinal();
      }
  
      @Override
      public int getItemCount() {
          return super.getItemCount() + ((hasExtraRow()) ? 1 : 0);
      }
  
      @Nullable
      @Override
      protected ChatMessage getItem(int position) {
  //        return hasExtraRow() ? super.getItem(position - 1) : super.getItem(position);
          return ((position == getItemCount() - 1) &amp;&amp; hasExtraRow()) ? null : super.getItem(position);
      }
  
      @Override
      public long getItemId(int position) {
          return position;
      }
  
      @MainThread
      void setNetworkState(@Nullable NetworkState newNetworkState) {
          if (newNetworkState == null)
              return;
          if (BuildConfig.DEBUG &amp;&amp; Looper.myLooper() != Looper.getMainLooper()) {
              throw new IllegalStateException("setNetworkState() called not on main thread!");
          }
          Timber.w("Paging adapter setNetworkState : %s", newNetworkState.getStatus().toString());
          NetworkState prevNetworkState = this.networkState;
          boolean hadExtraRow = hasExtraRow();
          this.networkState = newNetworkState;
          boolean hasExtraRow = hasExtraRow();
          if (hadExtraRow != hasExtraRow) {
              if (hadExtraRow) {
                  Timber.w("ChatAdapter notifyItemRemoved");
                  notifyItemRemoved(getItemCount() - 1); //(0);
              } else {
                  Timber.w("ChatAdapter notifyItemInserted");
                  notifyItemInserted(getItemCount() - 1); //(0);
              }
          } else if (hasExtraRow &amp;&amp; prevNetworkState != newNetworkState) {
              Timber.w("ChatAdapter notifyItemChanged");
              notifyItemChanged(getItemCount() - 1); //(0);
          }
      }
  
      private boolean hasExtraRow() {
          //TODO
  //        return networkState != null &amp;&amp; (super.getItemCount() == 0 || networkState != NetworkState.LOADED);
          return networkState != null &amp;&amp; networkState != NetworkState.LOADED;
      }
  
      void setStoreList(ArrayList&lt;Store&gt; storesArrayList) {
          this.storesArrayList = storesArrayList;
      }
  
      public void setUser(User user) {
          this.user = user;
      }
  }
  </code></pre>