我有一个 RecyclerView
,并向其中添加了一组数据。我想在最后一个 RecyclerView
可见项时添加更多数据到列表中。之后,我想进行 Web 服务调用并更新 RecyclerView
的数据。如何实现这个功能?
有任何建议吗?
我有一个 RecyclerView
,并向其中添加了一组数据。我想在最后一个 RecyclerView
可见项时添加更多数据到列表中。之后,我想进行 Web 服务调用并更新 RecyclerView
的数据。如何实现这个功能?
有任何建议吗?
一种选择是编辑您的 LayoutManager
。这里的想法是找到最后一个可见项的位置。如果该位置等于数据集的最后一项,则应触发重新加载。
@Override
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
final int result = super.scrollVerticallyBy(dy, recycler, state);
if (findLastVisibleItemPosition() == mData.length - 1) {
loadMoreData();
}
return result;
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
super.onLayoutChildren(recycler, state);
if (findLastVisibleItemPosition() == mData.length - 1) {
loadMoreData();
}
}
或者,您可以通过适配器的onBindViewHolder
方法来实现这一点,尽管这有点像“hack”:
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (position == mData.length - 1) {
// load more data here.
}
/// binding logic
}
第三个选项是将OnScrollListener添加到RecyclerView中。@velval在此页面上的答案很好地解释了这一点。
无论您选择哪种选项,都应包含代码以防止数据加载逻辑触发过多次(例如,在前一个请求获取更多数据完成并返回新数据之前)。
onBindViewHolder()
函数不是添加/加载数据的地方。请不要使用这种技术。 - Bugs HappenonBindViewHolder
不应该寻找更多数据。它只应该将数据绑定到ViewHolder
上。第二种方法要好一些,但是为了这么小的任务扩展LayoutManager
仍然是一项更大的工作。为什么不简单地使用RecyclerView.addOnScrollListener
并查看滚动达到了哪个位置,就像以下的Velval答案一样呢? - Bugs HappenrecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = lm.getChildCount();
int totalItemCount = lm.getItemCount();
int firstVisibleItemPosition= lm.findFirstVisibleItemPosition();
// Load more if we have reach the end to the recyclerView
if ( (visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0) {
loadMoreItems();
}
}
});
那么你的loadMoreItems()应该长成这个样子:
private void loadMoreItems() {
// init offset=0 the frist time and increase the offset + the PAGE_SIZE when loading more items
queryOffset = queryOffset + PAGE_SIZE;
// HERE YOU LOAD the next batch of items
List<Items> newItems = loadItems(queryOffset, PAGE_SIZE);
if (newItems.size() > 0) {
items.addAll(newItems);
adapter.notifyDataSetChanged();
}
}
另请参阅 Android - 检测RecyclerView中最后一个项目何时可见。
private fun isLastItemVisible(): Boolean {
val layoutManager = recycler_view.layoutManager
val position = layoutManager.findLastCompletelyVisibleItemPosition()
return position >= adapter.itemCount - 1
}
final boolean[] check = {true};
recyclerView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
if (!recyclerView.canScrollVertically(1)) {
// last item of recylerview reached.
if (check[0]) {
//your code for last reached item
scroll_handler.setVisibility(View.GONE);
}
} else {
scroll_handler.setVisibility(View.VISIBLE);
check[0] = false;
}
}
});
recyclerView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
if (!recyclerView.canScrollVertically(1))
// Bottom of recyler view.
arrow_img.setRotation(180);
}
}
});
android.support.v7.widget.RecyclerView.OnScrollListener
。 - pskinkonBindViewHolder
。 - pskinkposition == getItemCount() - 1
,那就意味着最后一个项目可见。 - pskink