recyclerview无尽滚动放缓
问题描述:
我阅读本指南实施endless scrolling并尝试过。这里是我的loadNextDataFromApi实现:recyclerview无尽滚动放缓
public void loadNextDataFromApi(int page, String term) {
movieService.getMovies(page, term)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<Movie>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(List<Movie> currentPageMovies) {
int start = allMovies.size();
allMovies.addAll(currentPageMovies);
adapter.notifyItemRangeInserted(start, currentPageMovies.size());
}
});
}
allMovies保存给定搜索的所有电影。这最初工作正常,但滚动最终加载较慢,从平滑滚动到一次3个电影(每个请求指定的数量)。我认为这是因为列表增长并占用越来越多的内存。文中提到,
前为了使分页系统继续工作可靠,你应该确保清除项目的适配器(或清除阵列之后通知适配器)追加新项目到列表
但改变onNext实现上述这打破了无尽的滚动:
@Override
public void onNext(List<Movie> currentPageMovies) {
allMovies.clear();
adapter.notifyDataSetChanged();
int start = allMovies.size();
allMovies.addAll(currentPageMovies);
adapter.notifyItemRangeInserted(start, currentPageMovies.size());
}
难道你需要保持在allMovies名单列表的前几页滚动备份?同时这样做与无尽的滚动可以导致OOM取决于页数
答
我一直致力于无尽滚动API调用,所以我可以与我分享我的代码,因为我发现我的列表做得很好。
首先使用此方法让recyclerview达到最后位置。
public void setRecyclerViewLastPositionListner(RecyclerView rv, final LinearLayoutManager mLayoutManager, final OnLastPositionReached onLastPositionReached) {
rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
userScrolled = true;
}
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// Here get the child count, item count and visibleitems
// from layout manager
visibleItemCount = mLayoutManager.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();
// Now check if userScrolled is true and also check if
// the item is end then update recycler view and set
// userScrolled to false
if (userScrolled && (visibleItemCount + pastVisiblesItems) == totalItemCount) {
userScrolled = false;
if (onLastPositionReached != null) onLastPositionReached.onReached();
}
}
});
}
这里使用的接口
public interface OnLastPositionReached {
void onReached();
}
使用它像
UtilitiesV2.getInstance().setRecyclerViewLastPositionListner(yourRecyclerView, mLayoutManager, new UtilitiesV2.OnLastPositionReached() {
@Override
public void onReached() {
callEBookApi();
}
});
这些变量持有启动下一个API调用的位置。
long start = 0;
private int lastReceivedListSize = 0;
int DEFAULT_LIMIT = 20;
考虑在这里调用你的api。
private void callEBookApi() {
start = booksAdapter.getItemCount();
if (start != 0 & lastReceivedListSize < DEFAULT_LIMIT)
return;
BeanLimit beanLimit = new BeanLimit();
beanLimit.setLimit(DEFAULT_LIMIT);
beanLimit.setStartpoint(start);
showProgressBar();
try {
callWebServicePost(Interactor.RequestCode_getEbooks, Interactor.Tag_getEbooks, Interactor.Method_getEbooks, new JSONObject(new Gson().toJson(beanLimit)), false, new OnResponseListener() {
@Override
public void onSuccess(int requestCode, Response responsePacket) {
hideProgressBar();
ArrayList<BookBean> list = responsePacket.getResponsePacket().getBooksList();
lastReceivedListSize = list.size();
updateListData(list);
}
@Override
public void onError(int requestCode, ErrorType errorType) {
FragmentEbooks.super.onError(requestCode, errorType);
hideProgressBar();
UtilProject.getInstance().showNothingToDisplayLayout(FragmentEbooks.this);
}
});
} catch (JSONException e) {
e.printStackTrace();
hideProgressBar();
}
}
private void updateListData(ArrayList<BookBean> list) {
if (list == null) listBooks = new ArrayList<>();
booksAdapter.insertItemsInList(list);
if (booksAdapter.getList().size() != 0) {
// UtilProject.getInstance().hideNothingToDisplayAndProgressBar(this); /*here you show placeholder if list empty*/
} else {
// UtilProject.getInstance().showNothingToDisplayLayout(this);
}
}
public void insertItemsInList(ArrayList<InvitationBean> myList) {
if (list == null) list = new ArrayList<>();
int lastIndex = list.size();
list.addAll(myList);
notifyItemRangeInserted(lastIndex, myList.size()); /*use this line for smooth scrolling if you use notifyDataSetChanged it will load all data again*/
// notifyDataSetChanged();
}
希望这可以帮助你。
谢谢你,但你仍然不断追加查询结果到更大的列表,就像在我发布的解决方案。你最终会得到一个OOM异常和加载速度减慢 – Marc
所以你想在该列表对象的解决方案一次只有最多100个项目。它会随着滚动而变老。 我认为你可以管理它。 如果你喜欢这样做,你可以管理一个数据库(如糖),在其中存储你的列表,你可以从数据库中获取数据并加载。 你可以做到男人。 – Khemraj