content: package com.ahmedabdelmeged.pagingwithrxjava.java.adapter;
  
  import android.arch.paging.PagedListAdapter;
  import android.support.annotation.NonNull;
  import android.support.v7.util.DiffUtil;
  import android.support.v7.widget.RecyclerView;
  import android.view.ViewGroup;
  
  import com.ahmedabdelmeged.pagingwithrxjava.R;
  import com.ahmedabdelmeged.pagingwithrxjava.java.data.NetworkState;
  import com.ahmedabdelmeged.pagingwithrxjava.java.model.User;
  
  import java.util.Objects;
  
  /**
   * Created by Ahmed Abd-Elmeged on 2/16/2018.
   */
  public class UserAdapter extends PagedListAdapter<User, RecyclerView.ViewHolder> {
  
      private NetworkState networkState;
  
      private RetryCallback retryCallback;
  
      public UserAdapter(RetryCallback retryCallback) {
          super(UserDiffCallback);
          this.retryCallback = retryCallback;
      }
  
      @NonNull
      @Override
      public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
          switch (viewType) {
              case R.layout.item_user:
                  return UserViewHolder.create(parent);
              case R.layout.item_network_state:
                  return NetworkStateViewHolder.create(parent, retryCallback);
              default:
                  throw new IllegalArgumentException("unknown view type");
          }
      }
  
      @Override
      public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
          switch (getItemViewType(position)) {
              case R.layout.item_user:
                  ((UserViewHolder) holder).bindTo(getItem(position));
                  break;
              case R.layout.item_network_state:
                  ((NetworkStateViewHolder) holder).bindTo(networkState);
                  break;
          }
      }
  
      private boolean hasExtraRow() {
          return networkState != null && networkState != NetworkState.LOADED;
      }
  
      @Override
      public int getItemViewType(int position) {
          if (hasExtraRow() && position == getItemCount() - 1) {
              return R.layout.item_network_state;
          } else {
              return R.layout.item_user;
          }
      }
  
      @Override
      public int getItemCount() {
          return super.getItemCount() + (hasExtraRow() ? 1 : 0);
      }
  
      /**
       * Set the current network state to the adapter
       * but this work only after the initial load
       * and the adapter already have list to add new loading raw to it
       * so the initial loading state the activity responsible for handle it
       *
       * @param newNetworkState the new network state
       */
      public void setNetworkState(NetworkState newNetworkState) {
          if (getCurrentList() != null) {
              if (getCurrentList().size() != 0) {
                  NetworkState previousState = this.networkState;
                  boolean hadExtraRow = hasExtraRow();
                  this.networkState = newNetworkState;
                  boolean hasExtraRow = hasExtraRow();
                  if (hadExtraRow != hasExtraRow) {
                      if (hadExtraRow) {
                          notifyItemRemoved(super.getItemCount());
                      } else {
                          notifyItemInserted(super.getItemCount());
                      }
                  } else if (hasExtraRow && previousState != newNetworkState) {
                      notifyItemChanged(getItemCount() - 1);
                  }
              }
          }
      }
  
      private static DiffUtil.ItemCallback<User> UserDiffCallback = new DiffUtil.ItemCallback<User>() {
          @Override
          public boolean areItemsTheSame(@NonNull User oldItem, @NonNull User newItem) {
              return oldItem.getId() == newItem.getId();
          }
  
          @Override
          public boolean areContentsTheSame(@NonNull User oldItem, @NonNull User newItem) {
              return Objects.equals(oldItem, newItem);
          }
      };
  
  }