ViewPager2滑动到末尾加载更多跳转首项,如何实现类似RecyclerView的分页加载?
问题修复方案
问题根源
- 每次加载完数据后重复调用
setPageTransformer():这个方法会触发ViewPager2重新布局,默认跳转回第0个页面,是你每次加载完回到首项的核心原因。 - 新增数据后未通知适配器更新:往数据源
statusModelList插入新数据后没有调用对应通知方法,适配器感知不到数据变更,也会导致页面展示异常。 - 缺少加载锁限制:滑动到最后一页时可能会重复触发加载请求,造成不必要的资源浪费。
修复步骤
1. 调整PageTransformer设置逻辑
PageTransformer只需要在初始化适配器的时候设置一次即可,不需要每次加载数据都重复调用,修改getPostsList()里的UI线程代码:
getActivity().runOnUiThread(() -> { if (shimmerFrameLayout.getVisibility() == View.VISIBLE) { shimmerFrameLayout.setVisibility(View.GONE); } if (progressIndicator.getVisibility() == View.VISIBLE) { progressIndicator.setVisibility(View.GONE); } if (viewPager2.getAdapter() == null) { statusAdapter = new StatusAdapter(getContext(), statusModelList, starClick, trendingClick); viewPager2.setAdapter(statusAdapter); // 页面切换动画仅初始化时设置一次 viewPager2.setPageTransformer(new ZoomInTransformation()); } else { // 通知适配器局部插入新数据,oldSize为新增数据前的列表长度,newDataSize为本次新增的条目数 int oldSize = statusModelList.size() - newDataSize; statusAdapter.notifyItemRangeInserted(oldSize, newDataSize); } // 加载完成重置加载锁 isLoading = false; });
如果你无法统计本次新增的条目数,可以临时调用
statusAdapter.notifyDataSetChanged()代替范围更新,但性能更低,建议优先使用范围更新。如果使用notifyDataSetChanged()出现页面跳转,需要重写适配器的getItemId()返回每个条目的唯一ID,同时调用statusAdapter.setHasStableIds(true)即可解决。
2. 增加加载锁避免重复请求
在类中新增成员变量标记加载状态,修改页面变化监听逻辑:
// 类成员变量,标记是否正在加载数据 private boolean isLoading = false; // ViewPager2页面监听逻辑 viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { @Override public void onPageSelected(int position) { super.onPageSelected(position); Log.i(APP_TAG, "item " + viewPager2.getAdapter().getItemCount() + " " + position); // 只有不在加载中、滑到最后一页、还有下页数据三个条件同时满足才触发加载 if (!isLoading && position == viewPager2.getAdapter().getItemCount() - 1 && value.hasData()) { isLoading = true; getPostsLists(value.getData().getRequestForNextResult()); Log.i(APP_TAG, value.toString()); } else if (!value.hasData()) { Log.i(APP_TAG, "data finish"); } } });
内容的提问来源于stack exchange,提问作者Lakshay Mudgal
相关产品推荐
相关产品推荐

