Skip to content

Instantly share code, notes, and snippets.

@mutkuensert
Created September 19, 2023 13:02
Show Gist options
  • Save mutkuensert/3a9b7d0671f9113cb741ffdb5c82160a to your computer and use it in GitHub Desktop.
Save mutkuensert/3a9b7d0671f9113cb741ffdb5c82160a to your computer and use it in GitHub Desktop.
An helper class to create remote mediator easily.
import androidx.paging.ExperimentalPagingApi
import androidx.paging.LoadType
import androidx.paging.PagingState
import androidx.paging.RemoteMediator
import com.github.michaelbull.result.Result
import com.github.michaelbull.result.get
import com.github.michaelbull.result.onFailure
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@OptIn(ExperimentalPagingApi::class)
class GenericRemoteMediator<T, R : Any>(
private val fetch: suspend (page: Int, clearLocalData: Boolean)
-> Result<List<T>, Throwable>,
private val getLastPageInLocal: suspend () -> Int?,
) : RemoteMediator<Int, R>() {
override suspend fun load(
loadType: LoadType,
state: PagingState<Int, R>
): MediatorResult {
val data = when (loadType) {
LoadType.REFRESH -> {
fetch.invoke(1, true).onFailure {
return MediatorResult.Error(it)
}
}
LoadType.PREPEND ->
return MediatorResult.Success(endOfPaginationReached = true)
LoadType.APPEND -> {
val lastPageNumber = withContext(Dispatchers.IO) {
getLastPageInLocal.invoke()
}
if (lastPageNumber == null) {
return MediatorResult.Success(endOfPaginationReached = true)
} else {
fetch.invoke(lastPageNumber + 1, false)
.onFailure {
return MediatorResult.Error(it)
}
}
}
}
return if (data.get().isNullOrEmpty()) {
MediatorResult.Success(endOfPaginationReached = true)
} else {
MediatorResult.Success(endOfPaginationReached = false)
}
}
}
//Example fetch function:
/*
private suspend fun fetchPopularTvShows(
page: Int,
clearLocalData: Boolean
): Result<List<PopularTvShowEntity>, Failure> {
return try {
coroutineScope {
withContext(Dispatchers.IO) {
val response = tvShowsApi.getPopularTvShows(page).toResult()
.getOrElse { throw Failure.empty() }
if (clearLocalData) {
tvShowDao.clearAllPopularTvShows()
}
response.results.map {
popularTvShowDtoMapper.mapToEntity(it, page)
}.also {
tvShowDao.insertPopularTvShows(it)
}.run { Ok(this) }
}
}
} catch (failure: Failure) {
Err(failure)
}
}
*/
//Example use:
/*
Pager(
config = PagingConfig(pageSize = 20),
remoteMediator = GenericRemoteMediator(
fetch = ::fetchPopularTvShows,
getLastPageInLocal = { tvShowDao.getAllPopularTvShows().lastOrNull()?.page }
),
pagingSourceFactory = { tvShowDao.getPopularTvShowsPagingSource() }
).flow.map { pagingData ->
pagingData.map {
PopularTvShow(
imageUrl = getImageUrl(it.posterPath),
id = it.id,
voteAverage = it.voteAverage,
name = it.title,
isFavorite = it.isFavorite
)
}
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment