title: Paging library storing only first fetched values in room database
body: <p>I have an application where i implemented paging library 3 to fetch data from api and paginate it , it works fine fetching data , the next implementation was to store the fetched data in room database , i have created the remotemediator class and wrote the code to store data , but the issue is that it stores only values of first page ( for example in my case im using the movie db api , each page fetched has 20 movies , and there are many pages ) , in my case it only saves the first 20 movies , even when i scroll , it is not storing more data , i have implemented the same exact code but seems to be the case , i faced it in an older project and now this one , i need some help , thank you in advance.</p>
  <ul>
  <li>Movies Dao</li>
  </ul>
  <pre><code> @Dao
  interface MoviesDao {
  
      @Query(&quot;SELECT * FROM movieTable ORDER BY id&quot;)
       fun getMovies() : PagingSource&lt;Int,Result&gt;
  
  
      @Insert(onConflict = OnConflictStrategy.REPLACE)
      suspend fun insertMovies(result: List&lt;Result&gt;)
  
  
      @Query(&quot;DELETE FROM movieTable&quot;)
      suspend fun clearMovies()
  
  
  }
  </code></pre>
  <ul>
  <li>RemoteKeys Dao</li>
  </ul>
  <pre><code>@Dao
  interface RemoteKeysDao {
  
      @Insert(onConflict = OnConflictStrategy.REPLACE)
      suspend fun insertAll(remoteKey: List&lt;RemoteKeys&gt;)
  
      @Query(&quot;SELECT * FROM remote_keys WHERE movieId = :movieId&quot;)
      suspend fun remoteKeysRepoId(movieId : Long): RemoteKeys?
  
      @Query(&quot;DELETE FROM remote_keys&quot;)
      suspend fun clearRemoteKeys()
  
  
  }
  </code></pre>
  <ul>
  <li>RemoteMediator Class</li>
  </ul>
  <pre><code>private  var MOVIES_API_STARTING_PAGE_INDEX = 1
  @ExperimentalPagingApi
  class MoviesMediator(
      private var authResponse: AuthResponse,
      private  var movieDatabase: MovieDatabase
  ) : RemoteMediator&lt;Int,Result&gt;() {
  
      override suspend fun load(loadType: LoadType, state: PagingState&lt;Int, Result&gt;): MediatorResult {
          val page = when (loadType) {
              LoadType.REFRESH -&gt; {
                  val remoteKeys = getRemoteKeyClosestToCurrentPosition(state)
                  remoteKeys?.nextKey?.minus(1) ?: MOVIES_API_STARTING_PAGE_INDEX
              }
              LoadType.PREPEND -&gt; {
                  val remoteKeys = getRemoteKeyForFirstItem(state)
                  val prevKey = remoteKeys?.prevKey
                  if (prevKey == null) {
                      return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
                  }
                  prevKey
              }
              LoadType.APPEND -&gt; {
                  val remoteKeys = getRemoteKeyForLastItem(state)
                  val nextKey = remoteKeys?.nextKey
                  if (nextKey == null) {
                      return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
                  }
                  nextKey
              }
          }
          try {
              val response = authResponse.getMovies(Constants.API_KEY, Constants.LANGUAGE, page).results
  
  
              val endOfPagination = response.isEmpty()
              movieDatabase.withTransaction {
                  // clear all tables in the database
                  if (loadType == LoadType.REFRESH) {
                      movieDatabase.remoteKeysDao().clearRemoteKeys()
                      movieDatabase.MovieDao().clearMovies()
                  }
                  val prevKey = if (page == MOVIES_API_STARTING_PAGE_INDEX) null else page - 1
                  val nextKey = if (endOfPagination) null else page + 1
  
                  val keys = response.map {
                      RemoteKeys(movieId = it.movieID, prevKey = prevKey, nextKey = nextKey)
                  }
                  movieDatabase.remoteKeysDao().insertAll(keys)
                  movieDatabase.MovieDao().insertMovies(response)
              }
              return MediatorResult.Success(endOfPaginationReached = endOfPagination)
          } catch (ex: Exception) {
              return MediatorResult.Error(ex)
          }
      }
  
      private suspend fun getRemoteKeyForFirstItem(state: PagingState&lt;Int, Result&gt;): RemoteKeys? {
          // Get the last page that was retrieved, that contained items.
          // From that last page, get the last item
          return state.pages.firstOrNull() { it.data.isNotEmpty() }?.data?.firstOrNull()
              ?.let { movieId -&gt;
                  // Get the remote keys of the last item retrieved
                  movieDatabase.remoteKeysDao().remoteKeysRepoId(movieId.movieID)
              }
      }
      private suspend fun getRemoteKeyClosestToCurrentPosition(state: PagingState&lt;Int, Result&gt;): RemoteKeys? {
          // The paging library is trying to load data after the anchor position
          // Get the item closest to the anchor position
          return state.anchorPosition?.let { position -&gt;
              state.closestItemToPosition(position)?.movieID?.let { movieId -&gt;
                  movieDatabase.remoteKeysDao().remoteKeysRepoId(movieId = movieId)
              }
          }
      }
  
      private suspend fun getRemoteKeyForLastItem(state: PagingState&lt;Int, Result&gt;): RemoteKeys? {
          // Get the last page that was retrieved, that contained items.
          // From that last page, get the last item
          return state.pages.lastOrNull() { it.data.isNotEmpty() }?.data?.lastOrNull()
                  ?.let { repo -&gt;
                      // Get the remote keys of the last item retrieved
                      movieDatabase.remoteKeysDao().remoteKeysRepoId(movieId = repo.movieID)
                  }
      }
  
  }
  </code></pre>
  <ul>
  <li>Passing RemoteMediator to paging data</li>
  </ul>
  <pre><code>    val dataFlow : kotlinx.coroutines.flow.Flow&lt;PagingData&lt;Result&gt;&gt; =
          Pager(getPagingConfig(),
          remoteMediator = MoviesMediator(authResponse,movieDatabase)){
              MoviePagingSource(authResponse)
          }.flow
              .cachedIn(viewModelScope)
  
  </code></pre>
  <ul>
  <li>Showing data in MainActivity</li>
  </ul>
  <pre><code>
   @ExperimentalPagingApi
      private fun setUpAdapterOnline(){
          moviesAdapter = MoviesAdapter()
          lifecycleScope.launchWhenStarted {
              moviesModel.dataFlow.collectLatest {
                  moviesAdapter.submitData(it)
              }
          }
  
          binding.recycler.adapter = moviesAdapter
          binding.recycler.adapter =  moviesAdapter.withLoadStateHeaderAndFooter(
              header = LoadingStateAdapter { moviesAdapter.retry() },
              footer = LoadingStateAdapter { moviesAdapter.retry() }
          )
      }
  </code></pre>