title: PageKeyedDataSource loadAfter called continuously
body: <p>I have a PageKeyedDataSource that continuously calls the loadAfter, and all the items are added in the Recyclerview multiple times. From the API side a null <code>lastEvaluatedKey</code> means give me the first page which kinda makes sense on why it keeps calling to get the first page but A. Shouldn't it stop if there are no more data to get (aka <code>params.key == null</code>? and B. Shouldn't the <code>COMPARATOR</code> in the Adapter disallow the same items being added multiple times? What am I missing?</p>
  
  <p>PageKeyedDataSource.kt</p>
  
  <pre><code>class ReservationsPageKeyedDataSource(private val retryExecutor: Executor) : PageKeyedDataSource&lt;String, Reservation?&gt;() {
  
      private var retry: (() -&gt; Any)? = null
  
      val initialLoad = MutableLiveData&lt;PagingNetworkState&gt;()
  
      fun retryAllFailed() {
          val prevRetry = retry
          retry = null
          prevRetry?.let {
              retryExecutor.execute {
                  it.invoke()
              }
          }
      }
  
      override fun loadInitial(
          params: LoadInitialParams&lt;String&gt;,
          callback: LoadInitialCallback&lt;String, Reservation?&gt;
      ) {
          val request = Api.reservationsService.getReservations(dateType = RERVATIONS_DATE_TYPE.future, last = null)
  
          initialLoad.postValue(PagingNetworkState.LOADING)
  
          // triggered by a refresh, execute in sync
          try {
              val response = request.execute()
              val originalData = response.body()?.result?.reservations
              val data = mutableListOf&lt;Reservation&gt;()
              // some data munipulation
              retry = null
              initialLoad.postValue(PagingNetworkState.LOADED)
  
              callback.onResult(
                  data.toList(),
                  null,
                  response.body()?.result?.lastEvaluatedKey.toString()
              )
          } catch (ioException: IOException) {
              retry = {
                  loadInitial(params, callback)
              }
              val error = PagingNetworkState.error(ioException.message ?: "unknown error")
              initialLoad.postValue(error)
          }
      }
  
      override fun loadBefore(
          params: LoadParams&lt;String&gt;,
          callback: LoadCallback&lt;String, Reservation?&gt;
      ) {
          // no-op
      }
  
      override fun loadAfter(
          params: LoadParams&lt;String&gt;,
          callback: LoadCallback&lt;String, Reservation?&gt;
      ) {
  
          // I tried adding an if statement here to check if the params.key is null or not but that didn't help
  
          Api.reservationsService.getReservations(dateType = RERVATIONS_DATE_TYPE.future, last = params.key)
              .enqueue(object : Callback&lt;ReservationListResponse&gt; {
                  override fun onFailure(call: Call&lt;ReservationListResponse&gt;, t: Throwable) {
                      retry = { loadAfter(params, callback) }
                  }
  
                  override fun onResponse(
                      call: Call&lt;ReservationListResponse&gt;,
                      response: Response&lt;ReservationListResponse&gt;
                  ) {
                      if (response.isSuccessful) {
                          val data = response.body()?.result?.reservations
                          retry = null
                          callback.onResult(
                              data.orEmpty(),
                              response.body()?.result?.lastEvaluatedKey.toString()
                          )
                      } else {
                          retry = { loadAfter(params, callback) }
                      }
                  }
              })
      }
  }
  </code></pre>
  
  <p>The comparator in the PagedListAdapter :</p>
  
  <pre><code>companion object {
          val COMPARATOR = object : DiffUtil.ItemCallback&lt;Reservation&gt;() {
              override fun areContentsTheSame(oldItem: Reservation, newItem: Reservation): Boolean =
                  oldItem == newItem
  
              override fun areItemsTheSame(oldItem: Reservation, newItem: Reservation): Boolean =
                  oldItem.id == newItem.id
          }
      }
  </code></pre>