0

What I want to do:

I want to fetch data from API and display it in recyclerView using Paging3 library

What is the issue:

The issue is that when I try to invoke fetching data from API using Paging3 library, the request isn't being invoked. I've checked in debugging and it doesn't work. getIngredients from viewModel is being invoked, but TransportUnitPagingSource isn't being invoked at all.

What I've tried:

1. Added required dependencies:

implementation("androidx.paging:paging-runtime-ktx:3.1.1")

2. Created data classes for API request:

data class PackageIngredientsResponseDto
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES) constructor(
    @JsonProperty("PackageIngredients")
    val packageIngredients: PagePackageIngredientDto
) : ApiResponseDto()
data class PagePackageIngredientDto
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES) constructor(
    @JsonProperty("content")
    val content: List<PackageIngredientDto>,
    @JsonProperty("empty")
    val empty: Boolean,
    @JsonProperty("first")
    val first: Boolean,
    @JsonProperty("last")
    val last: Boolean,
    @JsonProperty("number")
    val number: Int,
    @JsonProperty("numberOfElements")
    val numberOfElements: Int,
    @JsonProperty("pageable")
    val pageable: PageableObject,
    @JsonProperty("size")
    val size: Int,
    @JsonProperty("sort")
    val sort: SortObject,
    @JsonProperty("totalElements")
    val totalElements: Int,
    @JsonProperty("totalPages")
    val totalPages: Int
)
data class PackageIngredientDto(
    @JsonProperty("Id")
    val id: Int,
    @JsonProperty("Ckt")
    val ckt: Int,
    @JsonProperty("ExpirationDate")
    val expirationDate: String,
    @JsonProperty("Name")
    val name: String,
    @JsonProperty("Quantity")
    val quantity: Int,
    @JsonProperty("SerialNumber")
    val serialNumber: String
)

3. Created Service to fetch data using Retrofit

interface DispatchService {
    @GET("/ingredients/{labelCode}")
    suspend fun getIngredients(
        @Tag type: MockRequestType,
        @Path("labelCode") labelCode: String,
        @Query("page") page: Int,
        @Query("size") size: Int,
        @Query("sort") sort: String?
    ): PackageIngredientsResponseDto
}

4. Created PagingSource:

class TransportUnitPagingSource @Inject constructor(
    private val api: DispatchService,
    private val label: String
) : PagingSource<Int, PackageIngredientDto>() {


    override fun getRefreshKey(state: PagingState<Int, PackageIngredientDto>): Int? {
        return state.anchorPosition?.let { anchorPosition ->
            state.closestPageToPosition(anchorPosition)?.prevKey?.plus(1) ?: state.closestPageToPosition(anchorPosition)?.nextKey?.minus(1)
        }
    }

    override suspend fun load(params: LoadParams<Int>): LoadResult<Int, PackageIngredientDto> {
        val position = params.key ?: STARTING_PAGE_INDEX
        return try {
            val response = api.getIngredients(
                MockRequestType.Ingredients(
                    returnSuccess = true
                ),
                page = position,
                labelCode = label,
                size = params.loadSize,
                sort = "String"
            )
            val data = response.packageIngredients.content
            val nextPage = position +1
            val totalPages = response.packageIngredients.totalPages
            val nextKey = if (nextPage > totalPages) {
                null
            } else {
                nextPage
            }
            LoadResult.Page(
                data = data,
                prevKey = if (position == STARTING_PAGE_INDEX) null else position - 1,
                nextKey = nextKey
            )
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }

    companion object {
        private const val STARTING_PAGE_INDEX = 0
    }
}

5. Implemented getIngredients() in repository:

class DispatchRepository @Inject constructor(
    private val dispatchService: DispatchService
) {
    fun getIngredients(label: String): Flow<PagingData<PackageIngredientDto>> {
        return Pager(
            config = PagingConfig(pageSize = 20),
            pagingSourceFactory = { TransportUnitPagingSource(dispatchService, label) }
        ).flow
    }
}

6. Invoked getIngredients() in viewModel:

@HiltViewModel
class TransportUnitContentsViewModel @Inject constructor(
    private val wiFiService: WiFiService,
    private val repository: DispatchRepository
) : ViewModel() {
...
val packageIngredients: Flow<PagingData<PackageIngredientDto>> = repository.getIngredients("XXX").cachedIn(viewModelScope)
...
}

7. Tried to observe the result in fragment:

            viewLifecycleOwner.lifecycleScope.launch {
                viewModel.packageIngredients.collectLatest { pagingData ->
                    Log.d("PagingData", "$pagingData")
                }
            }

As I checked, everything should work as I did it using multiple sources. Can someone spot the issue?

Cuyer
  • 95
  • 8

0 Answers0