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<CreativeImageBean.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<CreativeImageBean.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()

補充:本文僅做記錄和供大家參考,如有需改進和錯誤之處,歡迎大家留言提出,謝謝!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章