Reputation: 1677
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
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
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
Reputation: 2409
Add
isLoading
boolean value it indicates toapiCall()
in progress.
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