Kotlin - Recyclerview 分页中的问题
Posted
技术标签:
【中文标题】Kotlin - Recyclerview 分页中的问题【英文标题】:Kotlin - Issue in Recyclerview Pagination 【发布时间】:2020-06-12 09:02:54 【问题描述】:我正在使用下面的方法来检查 Recyclerview 是否到达底部......即Recyclerview 中的最后一个位置是否可见:
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()
)
问题是当我将 Recyclerview 滚动到底部时,apiCall()
正在调用 twise 或 thrise。
你可以看到我正在管理一个布尔变量isLoadMore
在这里,我在调用我的网络服务时传递 1. 页面,2. 限制。
默认page是1,limit是20。下次会是2(page)和20(limit)。
因此,每次 Web 服务调用获取 20 个数据。
现在,如果在响应中我发现新的数据大小小于我的限制,我正在做的是将 isLoadMore 设置为 false。
可能是什么问题?你能指导我解决这个问题吗? 我怎么能完全知道这是recyclerview结束时调用服务的时间。
谢谢。
【问题讨论】:
您应该添加boolean
值,如isLoading
以防止api重复调用。
即您是在谈论添加 isScrolling 吗?
【参考方案1】:
将
isLoading
布尔值添加到apiCall()
正在进行中。
前)
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
【讨论】:
【参考方案2】:有一个专门的库为 recyclerView 提供分页。查看Paging Library。您将需要实现PageKeyedDataSource<Int, Item>()
,您可以在其中调用您的apiCall()
。有一个great tutorial 可以使用 Paging 库实现 Retrofit 调用
【讨论】:
【参考方案3】:最后,我做了如下:
取了一个变量:
private var isScrolling = true
在里面,OnScrollStateChanged:
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int)
super.onScrollStateChanged(recyclerView, newState)
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL)
isScrolling = true
检查它,在 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()
【讨论】:
以上是关于Kotlin - Recyclerview 分页中的问题的主要内容,如果未能解决你的问题,请参考以下文章
提供Kotlin阵列的补偿 .take(n:Int)。这是分页的好方法吗?