復(fù)現(xiàn)問(wèn)題步驟:
使用BaseRecyclerViewAdapterHelper加載列表,setEnableLoadMore(true)即可以加載更多
- 獲取到第一頁(yè)內(nèi)容,此時(shí)斷開(kāi)網(wǎng)絡(luò):
如果setLoadMoreView中的LoadMoreView有加載失敗的布局,則列表底部顯示加載失敗的布局;
如果未設(shè)置setLoadMoreView,則列表底部什么也沒(méi)有 - 接著連接網(wǎng)絡(luò),滑動(dòng)列表,發(fā)現(xiàn)無(wú)法再加載下一頁(yè),列表底部一直顯示加載失敗的布局
解決問(wèn)題:
- 在onBindViewHolder中判斷是列表的最后一項(xiàng)且loadMoreView中的狀態(tài)是LoadMoreView.STATUS_FAIL,將loadMoreView的狀態(tài)置為默認(rèn)loadMoreView.STATUS_DEFAULT
@Override
public void onBindViewHolder(CommonViewHolder holder, int position) {
if (position == getItemCount() - 1) {
if (mLoadMoreView != null && mLoadMoreView.getLoadMoreStatus() == LoadMoreView.STATUS_FAIL) {
mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT);//將狀態(tài)置為默認(rèn),是為了再次加載下一頁(yè)時(shí)可以加載
}
}
super.onBindViewHolder(holder, position);
}
- 在加載失敗時(shí),調(diào)用adapter.loadMoreFail()該方法會(huì)通知列表底部的item顯示加載失敗的布局,然后調(diào)用adapter.setEnableLoadMore(false),此處是為了防止在加載失敗后一直加載下一頁(yè)
- recyclerView添加OnScrollListener:在列表滑動(dòng)時(shí)認(rèn)為可以重新加載下一頁(yè),此時(shí)在網(wǎng)絡(luò)恢復(fù)時(shí)滑動(dòng)列表即可加載下一頁(yè)
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
setEnableLoadMore(true);//recyclerView再次滑動(dòng)時(shí)重新加載下一頁(yè)
}
});
原因探究:從源碼中尋求答案
- 查看 https://github.com/CymChad/BaseRecyclerViewAdapterHelper中BaseQuickAdapter的源碼,發(fā)現(xiàn)問(wèn)題來(lái)源于onBindViewHolder方法,如下:
@Override
public void onBindViewHolder(K holder, int position) {
//Add up fetch logic, almost like load more, but simpler.
autoUpFetch(position);
//Do not move position, need to change before LoadMoreView binding
是否加載更多在此處做判斷
autoLoadMore(position);
int viewType = holder.getItemViewType();
在加載失敗時(shí)到達(dá)列表底部,viewType為L(zhǎng)OADING_VIEW,顯示的未加載失敗的布局;也因此導(dǎo)致網(wǎng)絡(luò)恢復(fù)后無(wú)法加載下一頁(yè)
switch (viewType) {
case 0:
convert(holder, getItem(position - getHeaderLayoutCount()));
break;
case LOADING_VIEW:
mLoadMoreView.convert(holder);
break;
case HEADER_VIEW:
break;
case EMPTY_VIEW:
break;
case FOOTER_VIEW:
break;
default:
convert(holder, getItem(position - getHeaderLayoutCount()));
break;
}
}
所以需要在autoLoadMore中找到對(duì)應(yīng)的判斷條件
private void autoLoadMore(int position) {
if (getLoadMoreViewCount() == 0) {
return;
}
if (position < getItemCount() - mPreLoadNumber) {preLoadNumber默認(rèn)為1
return;
}
此處加載失敗,調(diào)用loadMoreFail,故loadMoreView的狀態(tài)為L(zhǎng)oadMoreView.STATUS_FAIL,直接返回,導(dǎo)致下面的加載下一頁(yè)的的監(jiān)聽(tīng)并未回調(diào)
if (mLoadMoreView.getLoadMoreStatus() != LoadMoreView.STATUS_DEFAULT) {
return;
}
mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_LOADING);
if (!mLoading) {
mLoading = true;
if (getRecyclerView() != null) {
getRecyclerView().post(new Runnable() {
@Override
public void run() {
加載更多
mRequestLoadMoreListener.onLoadMoreRequested();
}
});
} else {
加載更多
mRequestLoadMoreListener.onLoadMoreRequested();
}
}
}
總結(jié):
從上述源碼中可以看出,在加載失敗時(shí)調(diào)用loadMoreFail方法使loadMoreView的狀態(tài)置為STATUS_FAIL.在滑到列表底部時(shí)autoLoadMore中因?yàn)閘oadMoreView狀態(tài)為STATUS_FAIL,則直接返回,不再調(diào)用onLoadMoreRequested方法.
所以我采用了在判斷到達(dá)列表底部時(shí)將loadMoreView的狀態(tài)置為默認(rèn),就可以正常的回調(diào)加載更多了.但此時(shí)因?yàn)樵O(shè)置了加載更多的監(jiān)聽(tīng),在網(wǎng)絡(luò)未恢復(fù)時(shí)會(huì)不斷加載下一頁(yè),為了解決該問(wèn)題在loadMoreFail方法調(diào)用后將setEnableLoadMore設(shè)置為false,則不會(huì)不斷加載下一頁(yè)了.同樣設(shè)置了不可加載更多,則需要一個(gè)觸發(fā)條件,再將其設(shè)置為可以加載更多,故采用了recyclerView的滑動(dòng)監(jiān)聽(tīng),在列表滑動(dòng)時(shí)認(rèn)為有加載下一頁(yè)的需求,將其setEnableLoadMore置為true,使其可以加載下一頁(yè). 這樣在網(wǎng)絡(luò)恢復(fù)后,滑動(dòng)列表即可加載下一頁(yè).