7

I'm using the Android Paging 3 library in my project in order to load my data page by page. In this project, I'm not using database which means I'm using network only requests. The problem is that instead of loading pages based on the user scroll, it loads all pages at first. here is the code I'm using for the paging part of my project:

My RxPagingSource class:

class ReviewPagingSource constructor(
    private val network: Network,
    private val filter: ReviewFilter,
    private val config: Config,
    private val cacheFirstResponse: Boolean
) : RxPagingSource<Int, Review>() {

    override fun loadSingle(params: LoadParams<Int>): Single<LoadResult<Int, Review>> {
        return network.getReviews(
            filter.copy(page = (params.key ?: 0) , pageSize = params.loadSize),
            config,
            cacheFirstResponse
        )
            .subscribeOn(Schedulers.io())
            .map { toLoadResultPage(it, params) }
            .onErrorResumeNext {
                when (it) {
                    is TimeoutException,
                    is NoInternetException, is NetworkException, is UnexpectedResponseException -> Single.just(
                        LoadResult.Error(it)
                    )
                    else -> Single.error(it)
                }
            }
    }

    private fun toLoadResultPage(
        response: DataResponse<Review>,
        params: LoadParams<Int>
    ): LoadResult<Int, Review> {
        val page = params.key ?: 0
        return LoadResult.Page(
            response.results!!,
            if (page <= 0) null else page - 1,
            if (response.count ?: response.results?.count() ?: 0 < params.loadSize) null else page + 1,
            LoadResult.Page.COUNT_UNDEFINED,
            LoadResult.Page.COUNT_UNDEFINED
        )
    }

    override fun getRefreshKey(state: PagingState<Int, Review>): Int? {
        return state.anchorPosition?.let { state.closestPageToPosition(it) }?.nextKey
    }
}

My Pager is:

Pager(PagingConfig(pageSize = 5, initialLoadSize = 5,)) 
    { ReviewPagingSource(network, filter, config, true) }
    .flow.cachedIn(viewModelScope)

Related Gradle Part:

implementation "androidx.paging:paging-runtime-ktx:3.0.0-alpha13"
implementation "androidx.paging:paging-rxjava3:3.0.0-alpha13"

Any help would be appreciated.

Shift Delete
  • 1,015
  • 6
  • 13
  • 2
    By any chance are you using this in a nested scrolling scenario? What does your layout look like? – dlam Feb 28 '21 at 22:00
  • yes, I use NestedScrollView as the parent of my recycler view and now I can see this where my problem begins. Thank you @dlam – Shift Delete Mar 04 '21 at 09:01
  • 3
    No problem - in the nested scrolling case you must be careful not to give RV an infinite height as otherwise it will try to layout / load all items. If you're not able to use a well-defined height, you could also consider trying to use transformations like .flatMap(), .insertSeparators or use ConcatAdapter in place of nested scroll layout. – dlam Mar 05 '21 at 00:30
  • @dlam can you explain more on the solution. I am facing the same issue. – meetme Mar 31 '21 at 14:22
  • 4
    If you give RV an infinite height, it will try to bind every item because it thinks every item is visible. Nested scrolling is just not a supported use-case, you need to give RV a finite / bounded height. (or width, depending on scroll direction) – dlam Apr 01 '21 at 17:23

1 Answers1

2

In my case, this recipeId data type was long, but when I changed it to string it works fine. Then, instead of NestedScrollView use SmartNestedScrollview

@Entity(tableName = "table_recipe")
data class RecipeList(
        @PrimaryKey
        @field:SerializedName("recipe_id") var recipeId : String,
        @field:SerializedName("title") var title: String? = null,
)
SuperStormer
  • 4,997
  • 5
  • 25
  • 35