在滚动时在 recyclerview 中加载更多数据
Posted
技术标签:
【中文标题】在滚动时在 recyclerview 中加载更多数据【英文标题】:Loading more data in recyclerview on scroll 【发布时间】:2019-06-25 16:56:48 【问题描述】:我在包含 100 个项目的列表中获取 Json 数据。我将此列表传递给 recyclerview 适配器。但我一开始只想通过 10 个项目。在用户滚动列表的 10 项之后,它应该从列表中加载更多数据。我已经实现了滚动侦听器和其他适配器。我不确定如何将 json 列表中的 10 项传递给适配器。
滚动监听器
public abstract class PaginationScrollListener extends RecyclerView.OnScrollListener
LinearLayoutManager layoutManager;
/**
* Supporting only LinearLayoutManager for now.
*
* @param layoutManager
*/
public PaginationScrollListener(LinearLayoutManager layoutManager)
this.layoutManager = layoutManager;
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy)
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = layoutManager.getChildCount();
int totalItemCount = layoutManager.getItemCount();
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
if (!isLoading() && !isLastPage())
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount
&& firstVisibleItemPosition >= 0
&& totalItemCount >= getTotalPageCount())
loadMoreItems();
protected abstract void loadMoreItems();
public abstract int getTotalPageCount();
public abstract boolean isLastPage();
public abstract boolean isLoading();
适配器
public class PaginationAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
private static final int ITEM = 0;
private static final int LOADING = 1;
private List<Movie> movies;
private Context context;
private boolean isLoadingAdded = false;
public PaginationAdapter(Context context)
this.context = context;
movies = new ArrayList<>();
public List<Movie> getMovies()
return movies;
public void setMovies(List<Movie> movies)
this.movies = movies;
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch (viewType)
case ITEM:
viewHolder = getViewHolder(parent, inflater);
break;
case LOADING:
View v2 = inflater.inflate(R.layout.item_progress, parent, false);
viewHolder = new LoadingVH(v2);
break;
return viewHolder;
@NonNull
private RecyclerView.ViewHolder getViewHolder(ViewGroup parent, LayoutInflater inflater)
RecyclerView.ViewHolder viewHolder;
View v1 = inflater.inflate(R.layout.item_list, parent, false);
viewHolder = new MovieVH(v1);
return viewHolder;
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
Movie movie = movies.get(position);
switch (getItemViewType(position))
case ITEM:
MovieVH movieVH = (MovieVH) holder;
movieVH.textView.setText(movie.getTitle());
break;
case LOADING:
break;
@Override
public int getItemCount()
return movies == null ? 0 : movies.size();
@Override
public int getItemViewType(int position)
return (position == movies.size() - 1 && isLoadingAdded) ? LOADING : ITEM;
public void add(Movie mc)
movies.add(mc);
notifyItemInserted(movies.size() - 1);
public void addAll(List<Movie> mcList)
for (Movie mc : mcList)
add(mc);
public void remove(Movie city)
int position = movies.indexOf(city);
if (position > -1)
movies.remove(position);
notifyItemRemoved(position);
public void clear()
isLoadingAdded = false;
while (getItemCount() > 0)
remove(getItem(0));
public boolean isEmpty()
return getItemCount() == 0;
public void addLoadingFooter()
isLoadingAdded = true;
add(new Movie());
public void removeLoadingFooter()
isLoadingAdded = false;
int position = movies.size() - 1;
Movie item = getItem(position);
if (item != null)
movies.remove(position);
notifyItemRemoved(position);
public Movie getItem(int position)
return movies.get(position);
public MovieVH(View itemView)
super(itemView);
textView = (TextView) itemView.findViewById(R.id.item_text);
protected class LoadingVH extends RecyclerView.ViewHolder
public LoadingVH(View itemView)
super(itemView);
**获取 API 响应 **
private void callApi()
apiInterfacePages = ApiClient.getRetrofit().create(APIInterface.class);
Call<CamerasItem> camerasCall = apiInterfacePages.getCameras();
camerasCall.enqueue(new Callback<CamerasItem>()
@Override
public void onResponse(Call<CamerasItem> call, Response<CamerasItem> response)
CamerasItem camerasItem = response.body();
itemList = new ArrayList<>();
itemList = camerasItem.getItems();
Log.i("Item", "" + getChannel().getName());
for (int i = 0; i < itemList.size(); i++)
if (itemList.get(i).getCategory().equals(getChannel().getName()))
if (!itemList.get(i).getUrlMjpeg().endsWith("=mediaRedirect"))
String videoUrl = itemList.get(i).getUrlMjpeg();
String imageUrl = itemList.get(i).getThumbnail();
String name = itemList.get(i).getName();
String city = itemList.get(i).getCity();
String flag = itemList.get(i).getFlag();
String country= itemList.get(i).getCountry();
modelList.add(new MyModel(videoUrl, imageUrl, name, city, flag,country));
@Override
public void onFailure(Call<CamerasItem> call, Throwable t)
Log.i("Item", "" + t.getMessage());
);
那么现在如何第一次将 10 个项目传递给 recyclerview,并在每次滚动时传递 10 个项目。
【问题讨论】:
【参考方案1】:您必须在定义Recyclerview
的活动的xml 中设置Progressbar
。
loadThumbnail 是一个下载缩略图的函数。它只是给向下滚动一点延迟。现在适配器类的完整代码如下
public class CamerasAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
private List<MyModel> list;
private Activity mActivity;
private static final int TYPE_VIDEO = 0, TYPE_ADD = 1;
private static final int PAGE_LIMIT = 5;
private int mCurrentLimit = PAGE_LIMIT;
private boolean mIsLoading;
RelativeLayout mLoaderProgress;
public CamerasAdapter(FragmentActivity activity, RelativeLayout loaderLayout)
mActivity = activity;
mLoaderProgress = loaderLayout;
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i)
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.li_web_cam_view, viewGroup, false);
return new CamsViewHolder(itemView);
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i)
if (mCurrentLimit == (i + 1) && mCurrentLimit <= list.size() && !mIsLoading)
mLoaderProgress.setVisibility(View.VISIBLE);
mIsLoading = true;
loadThumbnail(0, i + 1);
else
//do nothing
((CamsViewHolder) viewHolder).onBindData(mActivity, list.get(i), i);
((CamsViewHolder) viewHolder).emptyView.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View view)
itemClickListner.onClick(i, ((CamsViewHolder) viewHolder).tvCamName, list.get(i));
);
private void loadThumbnail(final int count, int position)
try
if (count > 2 || position >= list.size())
new Handler().postDelayed(new Runnable()
@Override
public void run()
mIsLoading = false;
mCurrentLimit = mCurrentLimit + PAGE_LIMIT;
notifyItemChanged(position - count);
mLoaderProgress.setVisibility(View.GONE);
return;
, 2000);
else
if (list.get(position) == null)
loadThumbnail(count, position + 1);
else
Glide.with(mActivity).load(list.get(position).getImage_url()).downloadOnly(new SimpleTarget<File>()
@Override
public void onResourceReady(File resource, GlideAnimation<? super File> glideAnimation)
loadThumbnail((count + 1), (position + 1));
@Override
public void onLoadFailed(Exception e, Drawable errorDrawable)
loadThumbnail((count + 1), (position + 1));
);
catch (Exception e)
e.printStackTrace();
mLoaderProgress.setVisibility(View.GONE);
mIsLoading = false;
@Override
public int getItemCount()
return mCurrentLimit <= list.size() ? mCurrentLimit : list.size();
public void setData(List<MyModel> dataList)
this.list = dataList;
notifyDataSetChanged();
ItemClickListner itemClickListner;
public void setListener(ItemClickListner listener)
itemClickListner = listener;
ProgressLoadListener progressLoadListener;
public void setProgressLoadListener(ProgressLoadListener listener)
progressLoadListener = listener;
xml 文件的代码
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_
android:visibility="gone"
android:layout_
android:layout_above="@+id/loader_progress_bar_layout"
android:background="#f5f5f5"
android:layout_gravity="center" />
<RelativeLayout
android:layout_
android:layout_
android:layout_alignParentBottom="true"
android:id="@+id/loader_progress_bar_layout"
android:visibility="gone"
android:background="#fff"
>
<ProgressBar
android:id="@+id/progress_bar_loader"
android:layout_
android:layout_
android:layout_centerHorizontal="true"
android:layout_gravity="center" />
</RelativeLayout>
使用适配器初始化 Recyclerview
public class Main2Activity extends AppCompatActivity
RecyclerView recyclerView;
RelativeLayout layoutProgressBar;
CamerasAdapter adapter;
List<Item> itemList;
LinearLayoutManager mLayoutManager;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
layoutProgressBar = findViewById(R.id.loader_progress_bar_layout);
recyclerView = findViewById(R.id.recycler_view);
adapter = new CamerasAdapter(getActivity(), loaderLayout);
mLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setAdapter(adapter);
adapter.setProgressLoadListener(new ProgressLoadListener()
@Override
public void loadProgressBar()
layoutProgressBar.setVisibility(View.VISIBLE);
);
adapter.setData(setAdaperData());
public List<MyModel> setAdaperData()
List<MyModel> modelList = new ArrayList<>();
/*addItemsto list*/
return modelList;
【讨论】:
以上是关于在滚动时在 recyclerview 中加载更多数据的主要内容,如果未能解决你的问题,请参考以下文章
向下滚动然后再次向上滚动后,recyclerview 项目之间出现间隙。请看详情
如何使用 StaggeredGridLayoutManager 在 recyclerview 中实现无限滚动(分页)
使用 Glide 和 RecyclerView 上下滚动时图像消失,图像之间的空间增加