如何优雅的给recycleView增加下拉刷新和加载更多

recycleView作为一个新的控件,那是有其特点的。在日常的使用中,基本是可以代替listView和gridview使用的,同时,它还多了一种瀑布流的展示方式。

因此,个人是比较推荐开发者在项目开发过程中逐渐的使用recycview代替listview和gridview的。大家也都知道产品经理的想法永远是捉摸不定的,这次跟你说要垂直布局,好,等你用listview做完之后,就又跟你说觉得网格布局可能会好一点!!!ok,当你终于把控件转换成gridview,修改了大量的代码之后。如果,产品经理再跟你说,最后决定还是使用瀑布流得我样式好了, 你会不会有种崩溃的感觉。反正,我是会和PM打一架再说的。。。

总而言之,竟然最后还是得从了PM,何不一开始就已经做好准备呢?

RecyclView就是这样的一款新的控件。它把布局管理,item动画等都独立暴露了出来。虽然代码是增加了,但是却变得更加的灵活了,像上面的需求你只需要改动一行代码就可以实现了。

关于RecyView如何使用,网上已经有太多的教程了,因此我也不再讲解,大家可以参考下面这位大神的文章:

RecyclerView使用完全指南,是时候体验新控件了

这是一篇讲解的已经很详细的文章了,感谢作者的分享(还没有经过您的同意就放上你的文章,请见谅哈)

我这一片文章主要讲解的是如何优雅的增加下拉刷新和加载更多

关于下拉刷新

下拉刷新,在网上已经是有很多种的解决方案了,个人是比较喜欢通过在RecyView外层包裹一层 SwipeRefreshLayout来处理的。

SwipeRefreshLayout作为一个新的控件,使用简单,样式好看~

1.在xml中使用SwipeRefreshLayout包裹RecycleView


xml布局

2.绑定控件

refresh_layout= (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout);

//添加刷新监听器

refresh_layout.setOnRefreshListener(newSwipeRefreshLayout.OnRefreshListener() {

  @Override

  public voidonRefresh() {

  //加载数据

  backURL();

}

});

3.在加载完数据之后,记得要在UI线程中调用

if(refresh_layout.isRefreshing()){

    refresh_layout.setRefreshing(false);

}

记住这个操作只能在UI线程中执行,而且要是忘记了这个操作,那么即使在加载完数据之后,加载动画也不会停下来的

关于SwipRefreshLayout的更多用法可以参考

Android开发之SwipeRefreshLayout实现下拉刷新

总体的用法还是非常的简单易用的。好啦,下拉刷新就是这么的简单。

这一次的重点来了:

实现加载更多

网上实现加载更多的方法有很多。

今天由于想把项目的体积降下来,要砍掉一些没有必要的库,然后我就看到之前为了省时间直接就依赖了一个项目来实现瀑布流,然后瀑布流的布局在整个项目中,其实就只用了一次,就因为只用一次的东西而增加了一个依赖项目,真的是非常的蠢。所有我决定把这个依赖项目砍掉(并不是说这个项目不好)。既然要砍掉它,那就要找到它的替代品,所以我就把目光投向了RecycleView了,使用RecycleView实现瀑布流布局其实还是非常的快的,只要把 

mLayoutManager=newStaggeredGridLayoutManager(2,OrientationHelper.VERTICAL); 

就可以实现了。

关键还是在于实现下拉刷新和加载更多。下拉刷新在上面已经讲到怎么实现了,下面开始讲加载更多

在RecycleView中是没有onItemClickLinstener,OnItemLongClickListener以及加载更多等等的接口的。这一切都是要是自己实现的。本着不重复造轮子的精神,我先上google了一下。

发现大多是这样子的

拉刷新和上拉加载更多的RecyclerView,具有下拉和刷新动画

实现RecyclerView下拉刷新和上拉加载更多以及RecyclerView线性、网格、瀑布流效果演示

What the hell?(并没有说这样子的方法不科学,只是可以更简单的解决)

我只是要简单的实现加载更多,有必要改动这么多,还要增加footerview,还有对RecycleView增加OnScrollLinstener来监听是否到达最后一条,还有用 mLayoutManager.findLast...关键是瀑布流的layoutmanager还没有这个接口。。。

于是就开始思考,竟然单击事件,长按事件可以通过订阅的方式来实现,那么加载更多是不是也可以?

如果我在初始化Adapter的时候就告诉Adapter:如果到了最后一条数据就告诉我,我来加载更多。

本着这样的想法,我在Adapter的初始化总增加了这一个参数

ps:在评论中有同学指出如果不满一屏可能会频繁触发loadMoreListener,解决方法就是增加一个 参数 pageNum,用于判断当前数据满不满

publicListAdapter_pic(Context context,List listData,

OnItemClickListener listener,in.yeyeapp.listeners.OnLoadMoreListener loadMoreListener,int pageNum) {

mListener= listener;

mContext= context.getApplicationContext();

this.mInflater= LayoutInflater.from(mContext);

this.data= listData;

this.pageNum = pageNum;

//订阅加载更多

this.loadMoreListener= loadMoreListener;

}

实现加载更多的具体做法

mAdapter=newListAdapter_pic(getActivity(),mListAlbums,(OnItemClickListener)this, newOnLoadMoreListener() {

@Override

public voidonLoadMore() {

currentPage++;

nextPage();

}

});

OnLoadMore的具体实现

public interfaceOnLoadMoreListener {

public voidonLoadMore();

}

接下来是在合适的时候触发事件。

仔细阅读Adapter的代码我们会发现 onBindViewHolder 是负责绘制ItemView的函数,所以它是知道它当前已经画到第一几个Item了,所以这项重任就交给它了

@Override

public voidonBindViewHolder(ViewHolder holder, intposition) {

//新增对 loadMoreListener 的非空判断,以及对数据数目满屏的判断,防止触发空指针错误及数据不满而频繁触发加载更多

if(position == getItemCount() -1 && loadMoreListener != null && getCount() > pageNum) {

//告诉订阅者已经到最后一个了,可以加载更多了

loadMoreListener.onLoadMore();

}

//其他绑定资源的操作

。。。

}

这样,加载更多就大功告成了!!!

基本在网络良好的情况下,是可以无感的加载更多的

做法也是比较的简单

核心的思想就是让Adapter在绘制到最后一个view的时候告诉主线程说可以更新了。。。

如果想让加载更多更快一步执行,可以通过修改判断的条件

if(position == getItemCount() -1)

可以在倒数第二个,倒数第三个等就可以加载更多,这样可以让用户更加感知不到加载的过程

不过就要注意数据的个数了

如果这篇文章又帮到你的话,请点一下‘喜欢’,我会更努力的创作的

推荐阅读更多精彩内容