CymChad / BaseRecyclerViewAdapterHelper

BRVAH:Powerful and flexible RecyclerAdapter
http://www.recyclerview.org/
MIT License
24.34k stars 5.16k forks source link

onLoadMoreRequested不响应 #342

Closed AmoyJJ closed 8 years ago

AmoyJJ commented 8 years ago

package com.yelong.test.fragment;

import android.os.Bundle; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView;

import com.bumptech.glide.Glide; import com.chad.library.adapter.base.BaseQuickAdapter; import com.chad.library.adapter.base.BaseViewHolder; import com.chad.library.adapter.base.listener.OnItemClickListener; import com.yelong.test.chat99.R; import com.yelong.test.greendao.bean.ZiXun; import com.zhy.http.okhttp.OkHttpUtils; import com.zhy.http.okhttp.callback.StringCallback;

import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject;

import java.util.ArrayList;

import butterknife.BindView; import okhttp3.Call; import utils.PhpUrl; import utils.Xs; import utils.YUrl;

public class FmZinxunItem extends BaseFragment implements BaseQuickAdapter.RequestLoadMoreListener, SwipeRefreshLayout.OnRefreshListener {

@BindView(R.id.RecyclerView)
RecyclerView mRecyclerView;
@BindView(R.id.swipeLayout)
SwipeRefreshLayout mSwipeLayout;
private String id;
private int pageindex;
private View mLayout;
private informationItemAdapter mItemAdapter;
private TextView mTv_top;
private ImageView mIv_top;
private int mTOTAL_counter=100;
private int mCurrentCounter;
private ZiXun mHeaderData;
private View mHeader;
public void setId(String id) {
    this.id = id;
}
private ArrayList<ZiXun> zixuns = new ArrayList<ZiXun>();
private LayoutInflater inflater;

@Override
public void onAfterCreateView(View mLayout, LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    this.mLayout = mLayout;
    initView();
    addHeader();
    initEvent();
    getData(true, false);
}

@Override
protected int setLayoutId() {
    return R.layout.xrecycleview;
}

private void initView() {
    mRecyclerView.setHasFixedSize(true);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
    mItemAdapter = new informationItemAdapter(zixuns);
    mItemAdapter.openLoadAnimation();
    mItemAdapter.openLoadMore(10);
    mRecyclerView.setAdapter(mItemAdapter);
    mCurrentCounter = mItemAdapter.getData().size();
    mItemAdapter.setOnLoadMoreListener(this);

}
private void addHeader() {
    mHeader = mActivity.getLayoutInflater().inflate(R.layout.item_fragment_information_header, null);
    mTv_top = (TextView) mHeader.findViewById(R.id.zixun_fragment_list_item_tv_top);
    mIv_top = (ImageView) mHeader.findViewById(R.id.zixun_fragment_list_item_iv_big);
    mItemAdapter.addHeaderView(mHeader);
}

private void initEvent() {
    mSwipeLayout.setOnRefreshListener(this);
    mHeader.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Xs.Toast(mHeaderData.getTitle());
        }
    });
    mRecyclerView.addOnItemTouchListener(new OnItemClickListener() {
        @Override
        public void SimpleOnItemClick(BaseQuickAdapter baseQuickAdapter, View view, int posotion) {
            Xs.Toast(posotion + "");
        }
    });
    Xs.e("initEvent--" + mTOTAL_counter);

}

@Override
public void onRefresh() {
    getData(true, false);
    mItemAdapter.openLoadMore(10);
    Xs.e("onRefresh--" + mTOTAL_counter);
    mItemAdapter.removeAllFooterView();
    mSwipeLayout.setRefreshing(false);
}

@Override
public void onLoadMoreRequested() {
    Xs.e("mCurrentCounter--" + mCurrentCounter + "mTOTAL_counter--" + mTOTAL_counter);
    mRecyclerView.post(new Runnable() {
        @Override
        public void run() {
            if (mCurrentCounter >= mTOTAL_counter) {
                // 数据全部加载完毕就调用 loadComplete
                mItemAdapter.loadComplete();
                Xs.Toast("loadComplete");
            } else {
                // 如果有下一页则调用addData,不需要把下一页数据add到list里面,直接新的数据给adapter即可。
                pageindex++;
                mItemAdapter.addData(getLoadMoreData());
                mCurrentCounter = mItemAdapter.getData().size();
            }
        }

    });
}

class informationItemAdapter extends BaseQuickAdapter<ZiXun> {
    public informationItemAdapter(ArrayList<ZiXun> zixuns) {
        super(R.layout.item_fragment_information, zixuns);
    }

    @Override
    protected void convert(BaseViewHolder Holder, ZiXun ziXun) {
        Holder.setText(R.id.zixun_fragment_list_item_tv_title, ziXun.getTitle())
                .setText(R.id.zixun_fragment_list_item_tv_intro, ziXun.getDescription());
        Glide.with(mContext).load(ziXun.getLitpic()).crossFade()
                .into((ImageView) Holder.getView(R.id.zixun_fragment_list_item_iv_img));
    }
}

public void getData(final boolean refresh, final boolean loadmore) {
    YUrl url = new PhpUrl().p("m", "arclist").p("arc", id).p("page", pageindex + "").p("pagesize", "10").p("cache", "1");
    Xs.e(url.getUrl());
    OkHttpUtils.get().url(url.getUrl()).build().execute(new StringCallback() {
        @Override
        public void onError(Call call, Exception e, int id) {
        }

        @Override
        public void onResponse(String response, int id) {
            parseData(response, refresh, loadmore);
        }
    });
}

private void parseData(String result, boolean refresh, boolean loadmore) {
    try {
        JSONObject jsonObject = new JSONObject(result);
        JSONObject object = jsonObject.getJSONObject("count");
        mTOTAL_counter = object.getInt("countid");
        JSONArray jsonArray = jsonObject.getJSONArray("list");
        if (refresh) {
            zixuns.clear();
        }
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject beanObject = jsonArray.getJSONObject(i);
            String id = beanObject.getString("id");
            String title = beanObject.getString("title");
            String litpic = beanObject.getString("litpic");
            String description = beanObject.getString("description");
            ZiXun ziXun = new ZiXun(id, litpic, title, description);
            zixuns.add(ziXun);
        }
        if (refresh) {
            mHeaderData = zixuns.get(0);
            mTv_top.setText(mHeaderData.getDescription());
            Glide.with(mActivity).load(mHeaderData.getLitpic()).crossFade()
                    .into(mIv_top);
            zixuns.remove(0);
        }
        mCurrentCounter = zixuns.size();

    } catch (JSONException e) {
    }
    mItemAdapter.notifyDataSetChanged();
}

private ArrayList<ZiXun> getLoadMoreData() {
    final ArrayList<ZiXun> newData = new ArrayList<>();
    YUrl url = new PhpUrl().p("m", "arclist").p("arc", id).p("page", pageindex + "").p("pagesize", "10").p("cache", "1");
    Xs.e(url.getUrl());
    OkHttpUtils.get().url(url.getUrl()).build().execute(new StringCallback() {
        @Override
        public void onError(Call call, Exception e, int id) {
        }

        @Override
        public void onResponse(String response, int ss) {
            try {
                JSONObject jsonObject = new JSONObject(response);
                JSONObject object = jsonObject.getJSONObject("count");

// mTOTAL_counter = object.getInt("countid"); JSONArray jsonArray = jsonObject.getJSONArray("list"); for (int i = 0; i < jsonArray.length(); i++) { JSONObject beanObject = jsonArray.getJSONObject(i); String id = beanObject.getString("id"); String title = beanObject.getString("title"); String litpic = beanObject.getString("litpic"); String description = beanObject.getString("description"); ZiXun ziXun = new ZiXun(id, litpic, title, description); newData.add(ziXun); } } catch (JSONException e) { } } }); return newData; } }

AmoyJJ commented 8 years ago

@CymChad

CymChad commented 8 years ago

你的第一页数据是多少条?

AmoyJJ commented 8 years ago

首页也是十条啊。不过我好想remove了一条。。。。

CymChad commented 8 years ago

你rm了一条就不满足10条。。那就无法上拉。

CymChad commented 8 years ago

你一屏幕的item都没有那么无法上拉也是正常的。

AmoyJJ commented 8 years ago

在convert里面数据是直接获取列表对应行的。而我的header数据是获取第一页的首条数据。。。只能把它remove掉啊...那这要怎么办0.0

CymChad commented 8 years ago

你可以把pagesize设置成9,这样删除了一条也可以。

AmoyJJ commented 8 years ago

第二页返回10条再加载第三页又不行了。。。。

CymChad commented 8 years ago

怎么了?pageSize只限制了第一页的,如果第二页你通知了继续加载后续应该是不会出问题了,除非你调用了加载完成。

AmoyJJ commented 8 years ago

private void initView() { mRecyclerView.setHasFixedSize(true); mRecyclerView.setLayoutManager(new LinearLayoutManager(mActivity)); mItemAdapter = new informationItemAdapter(zixuns); mItemAdapter.openLoadAnimation(); mItemAdapter.openLoadMore(9); mRecyclerView.setAdapter(mItemAdapter); mCurrentCounter = mItemAdapter.getData().size(); mItemAdapter.setOnLoadMoreListener(this); }

@Override public void onLoadMoreRequested() { Xs.e("mCurrentCounter--" + mCurrentCounter + "mTOTAL_counter--" + mTOTAL_counter); mRecyclerView.post(new Runnable() { @Override public void run() { if (mCurrentCounter >= mTOTAL_counter) { // 数据全部加载完毕就调用 loadComplete mItemAdapter.loadComplete(); Xs.Toast("loadComplete"); } else { // 如果有下一页则调用addData,不需要把下一页数据add到list里面,直接新的数据给adapter即可。 // mItemAdapter.openLoadMore(10); pageindex++; getData(false,true); mCurrentCounter = mItemAdapter.getData().size(); } }

    });
}

private void parseData(String result, boolean refresh, boolean loadmore) { try { JSONObject jsonObject = new JSONObject(result); JSONObject object = jsonObject.getJSONObject("count"); mTOTAL_counter = object.getInt("countid"); JSONArray jsonArray = jsonObject.getJSONArray("list"); if (refresh) { zixuns.clear(); } for (int i = 0; i < jsonArray.length(); i++) { JSONObject beanObject = jsonArray.getJSONObject(i); String id = beanObject.getString("id"); String title = beanObject.getString("title"); String litpic = beanObject.getString("litpic"); String description = beanObject.getString("description"); ZiXun ziXun = new ZiXun(id, litpic, title, description); zixuns.add(ziXun); } if (refresh) { mHeaderData = zixuns.get(0); mTv_top.setText(mHeaderData.getDescription()); Glide.with(mActivity).load(mHeaderData.getLitpic()).crossFade() .into(mIv_top); mItemAdapter.remove(0); //如果加上这句pagesize填入9可以加载第二页第三页就不行了。没有这行填入10也是可以加载第二页。第三页不行。但是底部的加载动画会有 } mCurrentCounter = zixuns.size();

    } catch (JSONException e) {
    }
    mItemAdapter.notifyDataSetChanged();
}
CymChad commented 8 years ago

加载动画有,就证明调用了addData,没有数据是不是第三页的数据data没有数据?

CymChad commented 8 years ago

你可以debug一下,或者log一下。

AmoyJJ commented 8 years ago

不行。。。估计跟我这个数据结构有关系。。。哎

AmoyJJ commented 8 years ago

加载数据可以不要openLoadMore和addData嘛。。。

AmoyJJ commented 8 years ago

@CymChad 你在看一下代码吧。逻辑应该是正常。。但是第三页加载还是有缺陷

@Override
public void onAfterCreateView(View mLayout, LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    this.mLayout = mLayout;
    initView();
    addHeader();
    initEvent();
    getData(true, false);
}

@Override
protected int setLayoutId() {
    return R.layout.xrecycleview;
}

private void initView() {
    mRecyclerView.setHasFixedSize(true);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
    mItemAdapter = new informationItemAdapter(zixuns);
    mItemAdapter.openLoadAnimation();
    //mItemAdapter.openLoadMore(9);
    //屏蔽getData的openLoadMore 在此添加 当pagesize=10时不加载第二页。
    // 当pagesize=9时可以加载第二页。但第三页无法加载。会有正在加载的footerview
    mRecyclerView.setAdapter(mItemAdapter);
    mCurrentCounter = mItemAdapter.getData().size();

}

private void addHeader() {
    mHeader = mActivity.getLayoutInflater().inflate(R.layout.item_fragment_information_header, null);
    mTv_top = (TextView) mHeader.findViewById(R.id.zixun_fragment_list_item_tv_top);
    mIv_top = (ImageView) mHeader.findViewById(R.id.zixun_fragment_list_item_iv_big);
    mItemAdapter.addHeaderView(mHeader);
}

private void initEvent() {
    mSwipeLayout.setOnRefreshListener(this);
    mHeader.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Xs.Toast(mHeaderData.getTitle());
        }
    });
    mRecyclerView.addOnItemTouchListener(new OnItemClickListener() {
        @Override
        public void SimpleOnItemClick(BaseQuickAdapter baseQuickAdapter, View view, int posotion) {
            Xs.Toast(posotion + "");
        }
    });
    mItemAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
        @Override
        public void onLoadMoreRequested() {
            Xs.e("mCurrentCounter--" + mCurrentCounter + "mTOTAL_counter--" + mTOTAL_counter);
            mRecyclerView.post(new Runnable() {
                @Override
                public void run() {
                    if (mCurrentCounter >= mTOTAL_counter) {
                        // 数据全部加载完毕就调用 loadComplete
                        mItemAdapter.loadComplete();
                        Xs.Toast("loadComplete");
                    } else {
                        // 如果有下一页则调用addData,不需要把下一页数据add到list里面,直接新的数据给adapter即可。
                        pageindex++;
                        getData(false, true);
                    }
                }

            });
        }
    });
}

@Override
public void onRefresh() {
    getData(true, false);
    mItemAdapter.removeAllFooterView();
    mSwipeLayout.setRefreshing(false);
}

class informationItemAdapter extends BaseQuickAdapter<ZiXun> {
    public informationItemAdapter(ArrayList<ZiXun> zixuns) {
        super(R.layout.item_fragment_information, zixuns);
    }

    @Override
    protected void convert(BaseViewHolder Holder, ZiXun ziXun) {
        Holder.setText(R.id.zixun_fragment_list_item_tv_title, ziXun.getTitle())
                .setText(R.id.zixun_fragment_list_item_tv_intro, ziXun.getDescription());
        Glide.with(mContext).load(ziXun.getLitpic()).crossFade()
                .into((ImageView) Holder.getView(R.id.zixun_fragment_list_item_iv_img));
    }
}

public void getData(final boolean refresh, final boolean loadmore) {
    YUrl url = new PhpUrl().p("m", "arclist").p("arc", id).p("page", pageindex + "").p("pagesize", "10").p("cache", "1");
    Xs.e(url.getUrl());
    OkHttpUtils.get().url(url.getUrl()).build().execute(new StringCallback() {
        @Override
        public void onError(Call call, Exception e, int id) {
            Xs.e(e.toString());
        }

        @Override
        public void onResponse(String response, int id) {
            parseData(response, refresh, loadmore);
        }
    });
}

private void parseData(String result, boolean refresh, boolean loadmore) {
    if (loadmore) {
        mItemAdapter.openLoadMore(10);
    } else {
        mItemAdapter.openLoadMore(9);
    }
    //在此设置openLoadMore效果与在initView设置的结果一样。
    try {
        JSONObject jsonObject = new JSONObject(result);
        JSONObject object = jsonObject.getJSONObject("count");
        mTOTAL_counter = object.getInt("countid");
        JSONArray jsonArray = jsonObject.getJSONArray("list");
        if (refresh) {
            zixuns.clear();
        }
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject beanObject = jsonArray.getJSONObject(i);
            String id = beanObject.getString("id");
            String title = beanObject.getString("title");
            String litpic = beanObject.getString("litpic");
            String description = beanObject.getString("description");
            ZiXun ziXun = new ZiXun(id, litpic, title, description);
            zixuns.add(ziXun);
        }
        if (refresh) {
            mHeaderData = zixuns.get(0);
            mTv_top.setText(mHeaderData.getDescription());
            Glide.with(mActivity).load(mHeaderData.getLitpic()).crossFade()
                    .into(mIv_top);
            mItemAdapter.remove(0);
            //zixuns.remove(0); remove任意一个都是只能加载一次
        }
        mCurrentCounter = zixuns.size();
    } catch (JSONException e) {
    }
    mItemAdapter.notifyDataSetChanged();
    Xs.e(mItemAdapter.getPageSize());
}
CymChad commented 8 years ago

你可以不用addData,你可以直接自己改变外部的list数据之后调用dataAdded方法,dataAdded这个方法是刷新数据源和通知有下一页的作用。

CymChad commented 8 years ago

下拉刷新建议你使用,setNewData 这个会自动帮你清理原来的list,替换成你的newData

CymChad commented 8 years ago

我给你看下其开发者的使用方式

    private void refresh() {

        // 切换至Loading页面
        if (mQuickAdapter.getData().isEmpty()) {
            multiState.showLoading();
        }

        bmobQuery.setLimit(PAGE_SIZE);
        bmobQuery.setSkip((nextPage - 1) * PAGE_SIZE);
        bmobQuery.findObjectsByTableObservable()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new RxSubscribe<JSONArray>(mCxt) {
                    @Override
                    protected void _onNext(JSONArray jsonArray) {
                        loadPage(jsonArray);
                    }

                    @Override
                    protected void _onError(String message) {
                        if (mQuickAdapter.getData().isEmpty()) {
                            multiState.showError();
                        } else {
                            mQuickAdapter.showLoadMoreFailedView();
                        }
                    }

                    @Override
                    protected boolean showDialog() {
                        return false;
                    }
                });
    }

    private void loadPage(JSONArray jsonArray) {

        List<? extends BmobObject> datas = dataParser.parseJson(jsonArray.toString());

        if (isRefresh) {
            if (!datas.isEmpty()) {
                mQuickAdapter.setNewData(datas);
            }
            mQuickAdapter.openLoadMore(PAGE_SIZE);
            mQuickAdapter.removeAllFooterView();
            if (mSwipeRefreshLayout.isRefreshing()) {
                mSwipeRefreshLayout.setRefreshing(false);
            }
            isRefresh = false;
        } else {
            if (!datas.isEmpty()) {
                mQuickAdapter.addData(datas);
            }
        }

        if (mQuickAdapter.getData().isEmpty()) {
            multiState.showEmpty();
        } else {
            multiState.showContent();
        }

        // nextPage
        nextPage = jsonArray.length() < PAGE_SIZE ? 0 : nextPage + 1;

        if (nextPage == 0) {
            mRecyclerView.post(new Runnable() {
                @Override
                public void run() {
                    mQuickAdapter.loadComplete();
                    if (notLoadingView == null) {
                        notLoadingView = LayoutInflater.from(mCxt).inflate(R.layout.layout_footer_notloading,
                                (ViewGroup) mRecyclerView.getParent(), false);
                    }
                    mQuickAdapter.addFooterView(notLoadingView);
                }
            });
        }
    }

    @Override
    public void onRefresh() {
        if (mQuickAdapter.isLoading()) {
            mSwipeRefreshLayout.setRefreshing(false);
            return;
        }
        mRecyclerView.post(new Runnable() {
            @Override
            public void run() {
                isRefresh = true;
                nextPage = 1;
                refresh();
            }
        });

    }

    @Override
    public void onLoadMoreRequested() {
        if (nextPage == 0) {
            return;
        }
        mRecyclerView.post(new Runnable() {
            @Override
            public void run() {
                refresh();
            }
        });
    }
AmoyJJ commented 8 years ago

mItemAdapter.dataAdded();在数据解析完用这个替换notifydatasetchange就可以了。。。。感谢感谢。。但这是为啥0.0

CymChad commented 8 years ago

就几种情况,一个是下拉刷新你可以使用setNewData这个方法的意思就是清空之前的list填充新的list数据,一个是还有更多数据使用addData这个方法的意思就是追加list更多数据并且通知还有下一页数据,最后就是加载完毕loadComplete这个方法就是关闭掉加载监听,如果你要加一个尾部提示的话可以使用addFooterView,还有一种情况就是如果断网了,你可以调用showLoadMoreFailedView();这个方法会自动添加一个异常的item,点击可以继续上拉加载。

CymChad commented 8 years ago

notifydatasetchange 你只是通知了数据更新,没有告诉adapter还有下一页的通知。dataAdded里面做了通知数据更新还有通知adapter还有下一页的消息。

duduzai commented 7 years ago

mItemAdapter.dataAdded();没有这个方法,是库没有更新吗