I'm trying to implement Paging library in my project but until now it's not successful. I'm using Marvel API and the requests works well. The app was fully done before but I'm now to implement the library and I'm not getting any results. Basically, I was trying to collect the data like this:
Marvel API:
@GET("characters")
suspend fun recoverAll(
@Query("limit") limit: Int = PAGE_SIZE,
@Query("offset") offset: Int? = 0,
@Query("orderBy") orderBy: String = TITLE
): Response<CharacterResponseModel>
Repository:
interface MarvelApiRepository {
fun recoverAll(): Flow<PagingData<CharacterModel>>
}
class MarvelApiRepositoryImpl(private val api: MarvelApi): MarvelApiRepository {
override fun recoverAll(): Flow<PagingData<CharacterModel>> {
return Pager(
config = PagingConfig(
pageSize = PAGE_SIZE,
enablePlaceholders = false
),
pagingSourceFactory = { CharacterModelPagingSource(api) }
).flow
}
UseCase:
class RecoverCharactersFromApi(private val repository: MarvelApiRepository) {
operator fun invoke(): Flow<PagingData<CharacterModel>> {
return repository.recoverAll()
}
View Model:
fun fetch(): Flow<PagingData<CharacterModel>> {
return useCases.recoverCharactersFromApi().cachedIn(viewModelScope)
}
Recovering (without success):
private fun configDataCollection() = viewLifecycleOwner.lifecycleScope.launch {
viewModel.fetch().collectLatest { result ->
marvelCharactersAdapter.submitData(result)
}
This is my paging source:
class CharacterModelPagingSource(private val api: MarvelApi):
PagingSource<Int, CharacterModel>() {
override fun getRefreshKey(state: PagingState<Int, CharacterModel>): Int? {
return state.anchorPosition?.let { position ->
val anchorPage = state.closestPageToPosition(position)
anchorPage?.prevKey?.plus(1)?: anchorPage?.nextKey?.minus(1)
}
}
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, CharacterModel> {
return try {
val position = params.key?: STARTING_PAGE_INDEX
val offset = position * PAGE_SIZE
val response = api.recoverAll(offset = offset)
val nextKey = if(offset >= response.body()?.data!!.total) {
null
} else {
position + 1
}
return LoadResult.Page(
data = response.body()?.data!!.results.toList(),
prevKey = null,
nextKey = nextKey
)
} catch(e: java.lang.Exception) {
LoadResult.Error(e)
}
}
}
And the models works as: CharacterResponseModel contains the data, which is CharacterData, containing the results and the total number of items. The results are the CharacterModel as a list:
data class CharacterResponseModel(
@SerializedName("data")
val data: CharacterDataModel)
data class CharacterDataModel(
@SerializedName("results")
val results: List<CharacterModel>,
@SerializedName("total")
val total: Int
)
@Entity(tableName = CHARACTER_MODEL)
data class CharacterModel(
@PrimaryKey(autoGenerate = true)
@SerializedName("id")
val id: Int,
@SerializedName("name")
val name: String,
@SerializedName("description")
val description: String,
@SerializedName("thumbnail")
val thumbnail: ThumbnailModel): Serializable
Could anyone help me to achieve successfully this implementation? P.S.: I'm using Paging 3.1.1 and PagingDataAdapter