- Кино Дао
interface MoviesDao {
@Query("SELECT * FROM movieTable ORDER BY id")
fun getMovies() : PagingSource
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertMovies(result: List)
@Query("DELETE FROM movieTable")
suspend fun clearMovies()
}
- RemoteKeys Dao
interface RemoteKeysDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertAll(remoteKey: List)
@Query("SELECT * FROM remote_keys WHERE movieId = :movieId")
suspend fun remoteKeysRepoId(movieId : Long): RemoteKeys?
@Query("DELETE FROM remote_keys")
suspend fun clearRemoteKeys()
}
- Класс RemoteMediator
@ExperimentalPagingApi
class MoviesMediator(
private var authResponse: AuthResponse,
private var movieDatabase: MovieDatabase
) : RemoteMediator() {
override suspend fun load(loadType: LoadType, state: PagingState): MediatorResult {
val page = when (loadType) {
LoadType.REFRESH -> {
val remoteKeys = getRemoteKeyClosestToCurrentPosition(state)
remoteKeys?.nextKey?.minus(1) ?: MOVIES_API_STARTING_PAGE_INDEX
}
LoadType.PREPEND -> {
val remoteKeys = getRemoteKeyForFirstItem(state)
val prevKey = remoteKeys?.prevKey
if (prevKey == null) {
return MediatorResult.Success(endOfPaginationReached = remoteKeys != null)
}
prevKey
}
LoadType.APPEND -> {
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): 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 ->
// Get the remote keys of the last item retrieved
movieDatabase.remoteKeysDao().remoteKeysRepoId(movieId.movieID)
}
}
private suspend fun getRemoteKeyClosestToCurrentPosition(state: PagingState): 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 ->
state.closestItemToPosition(position)?.movieID?.let { movieId ->
movieDatabase.remoteKeysDao().remoteKeysRepoId(movieId = movieId)
}
}
}
private suspend fun getRemoteKeyForLastItem(state: PagingState): 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 ->
// Get the remote keys of the last item retrieved
movieDatabase.remoteKeysDao().remoteKeysRepoId(movieId = repo.movieID)
}
}
}
- Передача RemoteMediator в данные подкачки
Pager(getPagingConfig(),
remoteMediator = MoviesMediator(authResponse,movieDatabase)){
MoviePagingSource(authResponse)
}.flow
.cachedIn(viewModelScope)
- Отображение данных в MainActivity
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() }
)
}
Подробнее здесь: https://stackoverflow.com/questions/675 ... m-database
Мобильная версия