Jaimin Modi
Jaimin Modi

Reputation: 1677

Kotlin - Issue in Recyclerview Pagination

I am using below method to check that Recyclerview is reached up to bottom or not..i.e. last position in the Recyclerview is visible or not :

recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {

        override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
            super.onScrollStateChanged(recyclerView, newState)
        }

        override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            if (dy > 0) {
                visibleItemCount = recyclerView.getLayoutManager()!!.getChildCount()
                totalItemCount = recyclerView.getLayoutManager()!!.getItemCount()
                pastVisiblesItems =
                    (recyclerView.getLayoutManager() as GridLayoutManager).findFirstVisibleItemPosition()

                if (visibleItemCount + pastVisiblesItems >= totalItemCount && isLoadMore) {
                    // mocking network delay for API call
                    apiCall()
                }
            }
        }
    })

The Issue is apiCall() is calling twise or thrise sometime when I scrolls the Recyclerview to the bottom.

You can see I am managing a boolean variable isLoadMore

Here, I am passing 1. Page, 2. Limit while calling my webservice.

by default page is 1 and limit is 20. Next time it will be 2(page) and 20(limit).

So, fetching 20 data per web service call.

Now, if in response I found that newly data size is less than my limit, am doing is isLoadMore to false.

What might be the Issue ? Can you please guide me to resolve this issue. How can I perfectly know that This is the time to call service when recyclerview reached to end.

Thanks.

Upvotes: 1

Views: 1872

Answers (3)

Jaimin Modi
Jaimin Modi

Reputation: 1677

Finally, I have done as below :

Taken a varibale :

private var isScrolling = true

Inside, OnScrollStateChanged :

  override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
  super.onScrollStateChanged(recyclerView, newState)
  if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
         isScrolling = true
     }
  }

Checked It, in onScrolled :

override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            if (dy > 0) {
                visibleItemCount = recyclerView.getLayoutManager()!!.getChildCount()
                totalItemCount = recyclerView.getLayoutManager()!!.getItemCount()
                pastVisiblesItems =
                    (recyclerView.getLayoutManager() as GridLayoutManager).findFirstVisibleItemPosition()

                if (isScrolling && visibleItemCount + pastVisiblesItems >= totalItemCount && isLoadMore) {
                    isScrolling = false
                    // mocking network delay for API call
                   apiCall()
                }
            }
        }

Upvotes: 0

Alex Krafts
Alex Krafts

Reputation: 525

There is a dedicated library that provides paginations to the recyclerView. Check out Paging Library. You will need to implement PageKeyedDataSource<Int, Item>() where you can call your apiCall(). There is a great tutorial to implement Retrofit calls with Paging library

Upvotes: 1

Ethan Choi
Ethan Choi

Reputation: 2409

Add isLoading boolean value it indicates to apiCall() in progress.

Ex)

override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
            if (dy > 0) {
                visibleItemCount = recyclerView.getLayoutManager()!!.getChildCount()
                totalItemCount = recyclerView.getLayoutManager()!!.getItemCount()
                pastVisiblesItems =
                    (recyclerView.getLayoutManager() as GridLayoutManager).findFirstVisibleItemPosition()

                if (!isLoading && visibleItemCount + pastVisiblesItems >= totalItemCount && isLoadMore) {
                    // mocking network delay for API call
                    isLoading = true
                    apiCall()
                }
            }
        }

fun apiCall() {
    ...
    //when finished api request such as onResponse, onFailure function
    isLoading = false
}

Upvotes: 1

Related Questions