title: Invalidating custom PageKeyedDataSource makes recycler view jump
body: <p>I am trying to implement an android paging library with custom PageKeyedDataSource, This data source will query the data from Database and insert Ads randomly on that page. </p>
  
  <p>I implemented the paging, but whenever I scroll past the second page and invalidate the data source, the recycler view jumps back to the end of the second page.</p>
  
  <p>What is the reason for this?</p>
  
  <p>DataSource:</p>
  
  <pre><code>    class ColorsDataSource(
      private val colorsRepository: ColorsRepository
  ) : PageKeyedDataSource&lt;Int, ColorEntity&gt;() {
  
      override fun loadInitial(
          params: LoadInitialParams&lt;Int&gt;,
          callback: LoadInitialCallback&lt;Int, ColorEntity&gt;
      ) {
          Timber.i("loadInitial()  offset 0 params.requestedLoadSize $params.requestedLoadSize")
          val resultFromDB = colorsRepository.getColors(0, params.requestedLoadSize)
          // TODO insert Ads here
          callback.onResult(resultFromDB, null, 1)
      }
  
      override fun loadAfter(params: LoadParams&lt;Int&gt;, callback: LoadCallback&lt;Int, ColorEntity&gt;) {
          val offset = params.key * params.requestedLoadSize
          Timber.i("loadAfter()    offset $offset params.requestedLoadSize $params.requestedLoadSize")
          val resultFromDB = colorsRepository.getColors(
              offset,
              params.requestedLoadSize
          )
          // TODO insert Ads here
          callback.onResult(resultFromDB, params.key + 1)
      }
  
      override fun loadBefore(params: LoadParams&lt;Int&gt;, callback: LoadCallback&lt;Int, ColorEntity&gt;) {
          // No- Op
      }
  }
  </code></pre>
  
  <p>BoundaryCallback</p>
  
  <pre><code>class ColorsBoundaryCallback(
      private val colorsRepository: ColorsRepository,
      ioExecutor: Executor,
      private val invalidate: () -&gt; Unit
  ) : PagedList.BoundaryCallback&lt;ColorEntity&gt;() {
  
      private val helper = PagingRequestHelper(ioExecutor)
  
      /**
       * Database returned 0 items. We should query the backend for more items.
       */
      @MainThread
      override fun onZeroItemsLoaded() {
          helper.runIfNotRunning(PagingRequestHelper.RequestType.INITIAL) { pagingRequestHelperCallback -&gt;
              Timber.i("onZeroItemsLoaded() ")
              colorsRepository.colorsApiService.getColorsByCall(
                  ColorsRepository.getQueryParams(
                      1,
                      ColorViewModel.PAGE_SIZE
                  )
              ).enqueue(object : Callback&lt;List&lt;ColorsModel?&gt;?&gt; {
                  override fun onFailure(call: Call&lt;List&lt;ColorsModel?&gt;?&gt;, t: Throwable) {
                      handleFailure(t, pagingRequestHelperCallback)
                  }
  
                  override fun onResponse(
                      call: Call&lt;List&lt;ColorsModel?&gt;?&gt;,
                      response: Response&lt;List&lt;ColorsModel?&gt;?&gt;
                  ) {
                      handleSuccess(response, pagingRequestHelperCallback)
                  }
              })
          }
      }
  
      private fun handleSuccess(
          response: Response&lt;List&lt;ColorsModel?&gt;?&gt;,
          pagingRequestHelperCallback: PagingRequestHelper.Request.Callback
      ) {
          colorsRepository.saveColorsIntoDb(response.body())
          invalidate.invoke()
          Timber.i("onZeroItemsLoaded() with listOfColors")
          pagingRequestHelperCallback.recordSuccess()
      }
  
      /**
       * User reached to the end of the list.
       */
      @MainThread
      override fun onItemAtEndLoaded(itemAtEnd: ColorEntity) {
          Timber.i("onItemAtEndLoaded() ")
          helper.runIfNotRunning(PagingRequestHelper.RequestType.AFTER) { pagingRequestHelperCallback -&gt;
              val nextPage = itemAtEnd.nextPage?.toInt() ?: 0
              colorsRepository.colorsApiService.getColorsByCall(
                  ColorsRepository.getQueryParams(
                      nextPage,
                      ColorViewModel.PAGE_SIZE
                  )
              ).enqueue(object : Callback&lt;List&lt;ColorsModel?&gt;?&gt; {
                  override fun onFailure(call: Call&lt;List&lt;ColorsModel?&gt;?&gt;, t: Throwable) {
                      handleFailure(t, pagingRequestHelperCallback)
                  }
  
                  override fun onResponse(
                      call: Call&lt;List&lt;ColorsModel?&gt;?&gt;,
                      response: Response&lt;List&lt;ColorsModel?&gt;?&gt;
                  ) {
                      handleSuccess(response, pagingRequestHelperCallback)
                  }
  
              })
          }
      }
  
      private fun handleFailure(
          t: Throwable,
          pagingRequestHelperCallback: PagingRequestHelper.Request.Callback
      ) {
          Timber.e(t)
          pagingRequestHelperCallback.recordFailure(t)
      }
  }
  </code></pre>
  
  <p>Adapter's DiffUtil</p>
  
  <pre><code>class DiffUtilCallBack : DiffUtil.ItemCallback&lt;ColorEntity&gt;() {
          override fun areItemsTheSame(oldItem: ColorEntity, newItem: ColorEntity): Boolean {
              return oldItem == newItem
          }
  
          override fun areContentsTheSame(oldItem: ColorEntity, newItem: ColorEntity): Boolean {
              return oldItem.hexString == newItem.hexString
                      &amp;&amp; oldItem.name == newItem.name
                      &amp;&amp; oldItem.colorId == newItem.colorId
          }
      }
  </code></pre>
  
  <p>ViewModel</p>
  
  <pre><code>class ColorViewModel(private val repository: ColorsRepository) : ViewModel() {
  
      fun getColors(): LiveData&lt;PagedList&lt;ColorEntity&gt;&gt; = postsLiveData
  
      private var postsLiveData: LiveData&lt;PagedList&lt;ColorEntity&gt;&gt;
      lateinit var dataSourceFactory: DataSource.Factory&lt;Int, ColorEntity&gt;
      lateinit var dataSource: ColorsDataSource
  
      init {
          val config = PagedList.Config.Builder()
              .setPageSize(PAGE_SIZE)
              .setEnablePlaceholders(false)
              .build()
  
          val builder = initializedPagedListBuilder(config)
          val contentBoundaryCallBack =
              ColorsBoundaryCallback(repository, Executors.newSingleThreadExecutor()) {
                  invalidate()
              }
          builder.setBoundaryCallback(contentBoundaryCallBack)
          postsLiveData = builder.build()
      }
  
      private fun initializedPagedListBuilder(config: PagedList.Config):
              LivePagedListBuilder&lt;Int, ColorEntity&gt; {
  
          dataSourceFactory = object : DataSource.Factory&lt;Int, ColorEntity&gt;() {
              override fun create(): DataSource&lt;Int, ColorEntity&gt; {
                  dataSource =  ColorsDataSource(repository)
                  return dataSource
              }
          }
          return LivePagedListBuilder&lt;Int, ColorEntity&gt;(dataSourceFactory, config)
      }
  
      private fun invalidate() {
          dataSource.invalidate()
      }
  
      companion object {
          const val PAGE_SIZE = 8
      }
  }
  </code></pre>