XRecyclerview用法以及遇到的一些问题

最近使用XRecyclerview来实现数据的刷新和上拉加载更多操作,由于第一次使用,踩了不少坑,本文即为记录问题.

概述

XRecyclerview的基本用法就不多说了,github上面介绍的比较清楚,也可以查看作者提供的example来方便了解用法,github地址:XRecyclerview
本文要说明的主要是使用XRecyclerview实现后台数据的下拉刷新以及上拉加载更多的实战,作者提供的demo里面是静态放置的数据,相对于简单,真正对接后台数据时可能会有很多未知问题,本文主要扒扒自己项目中遇到的坑和数据刷新加载的具体实现方式.

用法思路

实现思路:目前通过xrecyclerview的开源代码来实现系列功能,加载数据传入type,值为1,2,3,分别表示初次加载,下拉刷新数据,上拉加载更多数据操作,刷新数据只需要重新放入数据,然后notifyDataSetChanged();即可.加载更多数据只需要在上拉时将获取数据放入之前数据list中刷新数据即可.这么说可能会比较抽象,让我们通过代码来具体看看怎么实现的吧.

核心代码:

  • 首先需要配置xRecyclerview的属性:
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()方法.

问题总览

  1. 点击第i个item,提示却是第i+1个item被点击
    问题原因:xrecyclerrview默认添加的header和footer,这就导致item的真实位置发生了变化,
    解决方案:将item的位置由holder.getLayoutPosition()改为position就可以了,adapter中修改代码如下:
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经过一些变换后所处的真正位置。
                 */
                    }
                });
  1. notifySetDataCahnged()无法刷新数据的问题:
    问题原因:先下拉刷新,然后上拉加载数据为空不显示,因为data的地址发生了变化,数据的刷新是在adapter中实现的,并且是新建一个list,然后调用了list.addAll(data),导致刷新data数据地址改变,刷新无效
    解决方案:新建一个list对象moreData来专门接收下拉刷新的数据,并且摒弃adapter中的addNewData()方法,直接data.clear()—data.addAll(moreData)—adapter.notifyDataChanged()

补充:本文仅做记录和供大家参考,如有需改进和错误之处,欢迎大家留言提出,谢谢!

你可能感兴趣的:(错误调试,上拉加载)