在我們實(shí)際的業(yè)務(wù)需求中著榴,如果是數(shù)據(jù)比較多啤挎,我們一般是采用分頁(yè)請(qǐng)求饲嗽,然后在客戶端進(jìn)行分頁(yè)展示炭玫。這里筆者使用了一個(gè)叫LoadMoreWrapper這個(gè)分頁(yè)加載框架,使用起來很方便貌虾,基本上不用去對(duì)RecyclerView的Adapter進(jìn)行什么操作吞加。
1、添加依賴
首先我們?cè)赼pp中的 build.gradle中添加對(duì)應(yīng)的依賴:
//LoadMoreWrapper尽狠,可以為RecyclerView設(shè)置分頁(yè)加載
implementation 'com.github.nukc:loadmorewrapper:v1.7.0'
另外我們?cè)谥鞴こ痰腷uild.gradle中的allprojects中做如下改動(dòng)
maven { url "https://jitpack.io" }
看源碼
public class LoadMoreWrapper {
private final LoadMoreAdapter mLoadMoreAdapter;
public LoadMoreWrapper(LoadMoreAdapter loadMoreAdapter) {
mLoadMoreAdapter = loadMoreAdapter;
}
public static LoadMoreWrapper with(RecyclerView.Adapter adapter) {
LoadMoreAdapter loadMoreAdapter = new LoadMoreAdapter(adapter);
return new LoadMoreWrapper(loadMoreAdapter);
}
public LoadMoreWrapper setFooterView(@LayoutRes int resId) {
mLoadMoreAdapter.setFooterView(resId);
return this;
}
public LoadMoreWrapper setFooterView(View footerView) {
mLoadMoreAdapter.setFooterView(footerView);
return this;
}
public View getFooterView() {
return mLoadMoreAdapter.getFooterView();
}
public LoadMoreWrapper setNoMoreView(@LayoutRes int resId) {
mLoadMoreAdapter.setNoMoreView(resId);
return this;
}
public LoadMoreWrapper setNoMoreView(View noMoreView) {
mLoadMoreAdapter.setNoMoreView(noMoreView);
return this;
}
public View getNoMoreView() {
return mLoadMoreAdapter.getNoMoreView();
}
public LoadMoreWrapper setLoadFailedView(@LayoutRes int resId) {
mLoadMoreAdapter.setLoadFailedView(resId);
return this;
}
public LoadMoreWrapper setLoadFailedView(View view) {
mLoadMoreAdapter.setLoadFailedView(view);
return this;
}
public View getLoadFailedView() {
return mLoadMoreAdapter.getLoadFailedView();
}
/**
* 監(jiān)聽加載更多觸發(fā)事件
* @param listener {@link com.github.nukc.LoadMoreWrapper.LoadMoreAdapter.OnLoadMoreListener}
*/
public LoadMoreWrapper setListener(LoadMoreAdapter.OnLoadMoreListener listener) {
mLoadMoreAdapter.setLoadMoreListener(listener);
return this;
}
/**
* 設(shè)置是否啟用加載更多
* @param enabled default true
*/
public LoadMoreWrapper setLoadMoreEnabled(boolean enabled) {
mLoadMoreAdapter.setLoadMoreEnabled(enabled);
if (!enabled) {
mLoadMoreAdapter.setShouldRemove(true);
}
return this;
}
/**
* 設(shè)置全部加載完后是否顯示沒有更多視圖
* @param enabled default false
*/
public LoadMoreWrapper setShowNoMoreEnabled(boolean enabled) {
mLoadMoreAdapter.setShowNoMoreEnabled(enabled);
return this;
}
/**
* 設(shè)置加載失敗
*/
public void setLoadFailed(boolean isLoadFailed) {
mLoadMoreAdapter.setLoadFailed(isLoadFailed);
}
/**
* 獲取原來的 adapter
*/
public RecyclerView.Adapter getOriginalAdapter() {
return mLoadMoreAdapter.getOriginalAdapter();
}
public LoadMoreAdapter into(RecyclerView recyclerView) {
recyclerView.setAdapter(mLoadMoreAdapter);
return mLoadMoreAdapter;
}
}
可以看到通過本類提供的with方法衔憨,LoadMoreWrapper能夠?qū)崿F(xiàn)對(duì)Adapter的裝飾。里面有很多方法袄膏,都有注釋践图,所以我們需要實(shí)現(xiàn)的功能用起來也很方便。
3.具體使用
LoadMoreWrapper.with(generateAdapter)
.setFooterView(R.layout.item_load_more)//底部view
.setNoMoreView(R.layout.item_load_complete)//沒有更多的提示
.setLoadFailedView(R.layout.item_load_failed)//加載失敗的提示
.setShowNoMoreEnabled(true)
.setListener(new OnLoadMoreListener() {
@Override
public void onLoadMore(LoadMoreAdapter.Enabled enabled) {
loadMoreEnabled = enabled;
presenter.getData(new PageParmForm(Constant.key,Constant.limit,Constant.order,Constant.page,Constant.sidx),NetWorkActivity.this);
}
})
.into(mRecyclerView);
使用起來也是很簡(jiǎn)單的沉馆,我們只需要對(duì)請(qǐng)求所得到的數(shù)據(jù)進(jìn)行判斷码党,然后對(duì)請(qǐng)求頁(yè)碼進(jìn)行自增,就可以實(shí)現(xiàn)分頁(yè)加載顯示斥黑。
@Override
public void showApplicationList(UserGuideSoftConfigRForm<List<UserguideSoftConfig>> Response) {
data=Response.getData();
if(pageIndex == 1){
generateAdapter.setData(data);//直接顯示當(dāng)前頁(yè)得items
generateAdapter.notifyDataSetChanged();//更新數(shù)據(jù)
}else{//頁(yè)碼不為1得時(shí)候
generateAdapter.addData(data);
}
//頁(yè)碼設(shè)置揖盘,每次獲取到數(shù)據(jù)后,先判斷數(shù)據(jù)集合是否不為空心赶,如果不為空就先使得頁(yè)碼加一岗宣,然后下次獲取數(shù)據(jù)的時(shí)候再進(jìn)行判斷
//直到如果數(shù)據(jù)為空的時(shí)候就顯示沒有更多數(shù)據(jù)了
if(data.size() > 0){
pageIndex ++;
Constant.page = pageIndex;
}else{
//沒有更多數(shù)據(jù)了
loadMoreEnabled.setLoadMoreEnabled(false);//停止加載更多數(shù)據(jù)
generateAdapter.notifyItemChanged(generateAdapter.getData().size());//更新指定位置,Adapter一般有得到數(shù)據(jù)和設(shè)置數(shù)據(jù)
}
}
當(dāng)沒有數(shù)據(jù)的時(shí)候我們要調(diào)用
generateAdapter.notifyItemChanged(generateAdapter.getData().size());//更新指定位
可能有人會(huì)問為什么是generateAdapter.getData().size()而不是generateAdapter.getData().size() -1呢提完,是因?yàn)樵跊]有數(shù)據(jù)可以展示的時(shí)候渐行,提示View會(huì)占一個(gè)Item,只有這樣嗜愈,這個(gè)提示Item才會(huì)生效。
這樣就實(shí)現(xiàn)了分頁(yè)加載與顯示了。
改進(jìn)與問題
在使用LoadMoreWrapper時(shí),筆者進(jìn)行了一番改動(dòng),結(jié)果發(fā)現(xiàn)在調(diào)用
generateAdapter.notifyItemChanged(generateAdapter.getData().size());是出現(xiàn)了一下錯(cuò)誤:
Called attach on a child which is not detached: ViewHolder{40e612c0 position=2 id=-1, oldPos=-1, pLpos:-1 no parent}
自己摸索了半天最終找到了解決方案:
1.第一步:
((SimpleItemAnimator) mRecyclerView.getItemAnimator()).setSupportsChangeAnimations(true);
2.第二步:
我們直接生命一個(gè)LoadMoreAdapter有咨,便于在操作過程中對(duì)他進(jìn)行各種設(shè)置
private LoadMoreAdapter mLoadMoreWrapper;
...
//設(shè)置分頁(yè)加載器
mLoadMoreWrapper = LoadMoreWrapper.with(generateAdapter)
.setFooterView(R.layout.item_load_more)//底部view
.setNoMoreView(R.layout.item_load_complete)//沒有更多的提示
.setLoadFailedView(R.layout.item_load_failed)//加載失敗的提示
.setLoadMoreEnabled(true)
.setShowNoMoreEnabled(isShowMore)//是否顯示沒有更多提示頁(yè)
.setListener(new OnLoadMoreListener() {
@Override
public void onLoadMore(LoadMoreAdapter.Enabled enabled) {
loadMoreEnabled = enabled;//enable為引用
//調(diào)用業(yè)務(wù)
presenter.getData(new PageParmForm(Constant.key,Constant.limit,Constant.order,Constant.page,Constant.sidx),NetWorkActivity.this);
}
})
.into(mRecyclerView);
...
@Override
public void showApplicationList(UserGuideSoftConfigRForm<List<UserguideSoftConfig>> Response) {
data=Response.getData();//得到應(yīng)用列表
if(pageIndex == 1){
generateAdapter.setData(data);//直接顯示當(dāng)前頁(yè)得items
}else{
//頁(yè)碼不為1得時(shí)候
generateAdapter.addData(data);
}
if( data.size()<10 && pageIndex == 1 )
{
//停止加載更多
mLoadMoreWrapper.setShowNoMoreEnabled(false);
loadMoreEnabled.setLoadMoreEnabled(false);//停止加載更多數(shù)據(jù)
}else if(data.size()>0){
pageIndex ++;
Constant.page = pageIndex;
loadMoreEnabled.setLoadMoreEnabled(true);//加載更多數(shù)據(jù)
}else {
//沒有更多數(shù)據(jù)了
loadMoreEnabled.setLoadMoreEnabled(false);//停止加載更多數(shù)據(jù)
mLoadMoreWrapper.setShowNoMoreEnabled(true);
generateAdapter.notifyItemChanged(generateAdapter.getData().size());//更新指定位置,Adapter一般有得到數(shù)據(jù)和設(shè)置數(shù)據(jù)
}
}
這樣就解決了這個(gè)問題,而且對(duì)這個(gè)Wrapper能達(dá)到比較好的控制效果蒸健。