最近使用XRecyclerview来实现数据的刷新和上拉加载更多操作,由于第一次使用,踩了不少坑,本文即为记录问题.
XRecyclerview的基本用法就不多说了,github上面介绍的比较清楚,也可以查看作者提供的example来方便了解用法,github地址:XRecyclerview
本文要说明的主要是使用XRecyclerview实现后台数据的下拉刷新以及上拉加载更多的实战,作者提供的demo里面是静态放置的数据,相对于简单,真正对接后台数据时可能会有很多未知问题,本文主要扒扒自己项目中遇到的坑和数据刷新加载的具体实现方式.
实现思路:目前通过xrecyclerview的开源代码来实现系列功能,加载数据传入type,值为1,2,3,分别表示初次加载,下拉刷新数据,上拉加载更多数据操作,刷新数据只需要重新放入数据,然后notifyDataSetChanged();即可.加载更多数据只需要在上拉时将获取数据放入之前数据list中刷新数据即可.这么说可能会比较抽象,让我们通过代码来具体看看怎么实现的吧.
xRecyclerView.setPullRefreshEnabled(true);
xRecyclerView.setLoadingMoreEnabled(true);
xRecyclerView.setRefreshProgressStyle(ProgressStyle.BallSpinFadeLoader);
xRecyclerView.setLoadingMoreProgressStyle(ProgressStyle.Pacman);
xRecyclerView.setLoadingListener(new XRecyclerView.LoadingListener() {
@Override
public void onRefresh() {
new Handler().postDelayed(new Runnable(){
public void run() {
getWorksData(1,2);
}
}, 2000);
}
@Override
public void onLoadMore() {
count+=1;
loge("第几次加载=="+count);
new Handler().postDelayed(new Runnable(){
public void run() {
getWorksData(count,3);
}
}, 2000);
}
});
从上面代码可以看到,需要先设置下拉刷新和加载更多可执行,为true,然后设置它的加载样式,有多种样式可以选择,具体参考xrecyclerview的github介绍,接下里设置一下loadingListener即可.我们需要实现它的两个方法:刷新回调方法onRefresh()和加载更多方法onLoadingMore(),即分别在这两个方法中实现自己的刷新和加载数据逻辑即可.
getWorksData(参数1,参数2)即为获取后天数据的方法.参数1是指数据请求的次数,也指代请求后台的数据页数,初始化为1;参数2表示当前数据的操作模式(为1:初次请求数据,为2:刷新数据,为3:加载更多数据).由于是公司项目,这里我附上okhttp请求的onResponse()方法得到数据后的处理:
loadingDialog.dismiss();
creativeImageBean = JSONObject.parseObject(response, CreativeImageBean.class);
if (creativeImageBean!=null && creativeImageBean.getCode() == 1000) {
if(type==1){
//是初次加载
loge("初次加载数据");
data=creativeImageBean.getData().getList();
Message msg = Message.obtain(handler);
msg.what = GET_DATA;
handler.handleMessage(msg);
}else if(type==2){
//下拉刷新
//data = new ArrayList.CreativeImageList.CreativeImageData>();
updateData=creativeImageBean.getData().getList();
count = 1;
loge("刷新了");
xRecyclerView.refreshComplete();
if (workAdapter != null) {
Message msg = Message.obtain(handler);
msg.what = UPDATE_DATA;
handler.sendMessage(msg);
} else {
Message msg = Message.obtain(handler);
msg.what = GET_DATA;
handler.sendMessage(msg);
}
}else if(type==3){
//加载更多
//moreData = new ArrayList.CreativeImageList.CreativeImageData>();
moreData = creativeImageBean.getData().getList();
loge("加载更多数据页数==" + count+"---数据量--"+moreData.size());
if (moreData != null && moreData.size() > 0) {
data.addAll(moreData);
loge("data加载更多数据后的地址=="+data.hashCode());
loge("作品总数据长度==" + data.size());
// Message msg = Message.obtain(handler);
// msg.what = UPDATE_DATA;
// handler.sendMessage(msg);
if(workAdapter!=null){
loge("workAdapter不为空");
workAdapter.notifyDataSetChanged();
}else {
loge("workAdapter为空");
workAdapter = new WorksShowAdapter(MemoryWorksActivity.this,data);
xRecyclerView.setAdapter(workAdapter);
}
xRecyclerView.loadMoreComplete();
//workAdapter.addNewData(data);//添加数据
//如果添加moreData,为空是什么原因
} else {
loge("moreData数据为空");
// xRecyclerView.setLoadingMoreEnabled(false);
// toast(getString(R.string.act_home_loadmore));
xRecyclerView.loadMoreComplete();
}
}
}
第一次使用markdown写博客,怎么感觉代码很乱…
如果感觉if-else比较乱,可以使用switch-case,数据刷新即需要重新获取后台最新数据,比如用户上传了自己的作品,那么就需要在他将作品上传成功后刷新数据,让用看到自己的作品,而加载更多则是根据用户上拉的操作,判断需要请求的数据页数,并将数据放入原有的data中,然后刷新数据,数据请求和刷新是耗时的,所以开启子线程,部分代码如下:
@Override
public void handleMessage(Message msg, Activity weakReferenceActivity) {
switch (msg.what) {
case GET_DATA:
//显示数据和处理
loge("来获取数据和显示了");
xRecyclerView.setLayoutManager(new GridLayoutManager(MemoryWorksActivity.this,2));
workAdapter = new WorksShowAdapter(MemoryWorksActivity.this,data);
loge("data初始的地址==="+data.hashCode());
xRecyclerView.setAdapter(workAdapter);
workAdapter.setOnMyItemClickListener(new CreativeImageAdapter.OnMyItemClickListener() {
@Override
public void onItemClick(View view, int position) {
//相关操作
}
@Override
public void onItemLongClick(View view, int position) {
}
});
break;
case UPDATE_DATA:
//刷新数据
loge("来刷新数据了,这时data数量为"+data.size());
//workAdapter.addNewData(data);
data.clear();
data.addAll(updateData);
workAdapter.notifyDataSetChanged();
break;
}
}
刷新数据需要先清除原有数据,然后放入最新数据,接着调用adaper.motifyDataSetChange()方法.
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//int pos = holder.getLayoutPosition();//点击的item控件的位置
myListener.onItemClick(holder.itemView, position);
/*
此方法返回的pos值与onBindViewHolder方法传入的position值有可能不同。
根据SDK中的解释,在Recyclerview 进行添加、移除item等操作时,position位置可能会变化,
而所有的adapter的刷新并不总是及时的,
只有这个方法返回的才是当前item经过一些变换后所处的真正位置。
*/
}
});
补充:本文仅做记录和供大家参考,如有需改进和错误之处,欢迎大家留言提出,谢谢!