SmartRefreshLayout+BaseRecyclerviewAdapterHelper使用MVP方式實現下拉重新整理

路國強發表於2018-08-02

關鍵字:SmartRefreshLayout使用 下拉重新整理 上拉載入 BaseRecyclerviewAdapterHelper

前言
下拉重新整理和上拉載入是每個APP中最基本的功能,這裡將這個功能進行整理。可以作為一個模板程式碼去使用,這樣避免了每次開發都要去思考,直接複製貼上使用即可。

實現的功能點:
1.使用MVP實現下拉重新整理及載入更多;
2.採用懶載入,禁止viewPager預載入,區分出兩種重新整理:初始化重新整理、下拉重新整理;
3.採用BaseRecyclerviewAdapterHelper的上拉載入達到更好的上拉載入效果;
4.上拉載入:無資料、載入錯誤、資料全部載入完成三種檢視的區分顯示;
5.下拉重新整理無資料空檢視的展示;

目錄

  • 技術方案選型
  • 具體程式碼
  • 分頁欄位的理解

利用SmartRefreshLayout實現下拉重新整理
利用 baserecyclerviewadapterhelper 實現載入更多

1.Presenter 層,DemoPresenter.java 如下,只列出簡要P層獲取新聞列表,M層的實現這裡就不列出了,這個不是本文重點。

public class DemoPresenter {
  DemoRepository mRepository;

  // 獲取新聞列表
  public void getNews(int pageNumber, int loadType){
    mRepository.loadNewsListByTopic(pageNumber, new DemoDataSource.LoadNewsCallback() {
      
      @Override
      public void onNewsLoaded(List<News> newsList) {
        mView.loadSuccess(newsList, loadType);
      }
      
    });
  }
}

佈局設定

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fff"
    android:orientation="vertical">
    
    <!— 這裡遮蔽掉載入更多功能 -->
    <com.scwang.smartrefresh.layout.SmartRefreshLayout
        android:id="@+id/refreshLayout"
        android:layout_width=“match_parent"
        app:srlEnableLoadMore="false"
        android:layout_height="match_parent">
        
        <!-- 新增經典下拉頭部重新整理 -->
        <com.scwang.smartrefresh.layout.header.ClassicsHeader
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:srlAccentColor="@android:color/white" />
        
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1" />
        
    </ai.botbrain.smartrefresh.layout.SmartRefreshLayout>
</LinearLayout>

程式碼中設定

public class TestFragment extends BaseFragment implements TestView {
  
  // 標識分頁的欄位
  private int mPageNum = 0;
  private static final int COUNT = 10;

  private int mRefreshType;//mRefreshType變數名用小寫,防止看混淆
  // 首次重新整理
  public static final int FIRST_LOAD = 1;
  // 重新整理
  public static final int REFRESH = 2;
  // 上拉載入
  public static final int LOAD_MORE = 3;

  private View mNoDataView;

  @BindView(R.id.refreshLayout)
  SmartRefreshLayout mRefreshLayout;
  
  @BindView(R.id.recyclerView)
  PowerfulRecyclerView mRecyclerView;
  
  private MyAdapter mAdapter;
  
  private MyPresenter mPresenter;
  
  @Override
  public void initData() {
    super.initData();
    mAdapter = new MyAdapter();
    // 自定義載入中,載入失敗,載入完成的佈局
    mAdapter.setLoadMoreView(new CustomLoadMoreView());
  }

  @Override
  public void initView(View rootView) {
    super.initView(rootView);
    mNoDataView = getLayoutInflater().inflate(R.layout.empty_view, (ViewGroup) mRecyclerView.getParent(), false);
  }  

  @Override
  public void initListener() {
    super.initListener();
    
    // 下拉重新整理回撥
    mRefreshLayout.setOnRefreshListener(refreshLayout -> {
     mPageNum = 0;
     mPresenter.loadDataList(mPageNum, FIRST_LOAD);
    });
    
    // 上拉載入回撥
    mAdapter.setOnLoadMoreListener(() -> {
      mPresenter.loadDataList(mPageNum, LOAD_MORE);
    }, mRecyclerView);
    
    mRecyclerView.setAdapter(mAdapter);
    
    // 剛進來的時候來個初始化重新整理
    mRefreshLayout.autoRefresh();
  }
  
  @Override
  public void onLoadNewsSuccess(List<Circle> data, int loadType) {
    // 防範空指標發生
    if (ListUtils.isEmpty(data))
      data = new ArrayList<>();    
    
    mPageNum++;
    // int size = data == null ? 0 : data.size();
    int size = data.size();
    
    // mRefreshLayout.finishLoadmore();
    mRefreshLayout.finishRefresh(0);
    
    // 注意:不要忘記新增 break 否則~
    switch (loadType) {
      case FIRST_LOAD:
        mAdapter.initRefresh(data);// 如果data為null這裡就會引發空指標
        break;
      case REFRESH:
        mAdapter.initRefresh(data);
        break;
      case LOAD_MORE:
        mAdapter.loadMoreData(data);
        break;
    }
    
    if (mAdapter.getData().size() == 0) {    //空檢視情況
      mAdapter.setEmptyView(noDataView);        
    } else if (size == 0) {                  //上拉載入出來的資料為0,認為載入結束
      mAdapter.loadMoreEnd(false);
    } else {//完成了本次載入,還有更多資料(注意邏輯是在else中,這裡寫錯可能導致不停的上拉載入資料)
      mAdapter.loadMoreComplete();
    }
  }
  
  // 載入失敗的情況,顯示重試頁面
  @Override
  public void onLoadNewsError() {
    // 彈出提示
    mTipView.show();
    
    // 如果一開始進入沒有資料,顯示重試佈局
    if (ListUtils.isEmpty(mAdapter.getData)) {
      showRetry();
    } else { // 顯示(載入失敗,請點我重試)
      mAdapter.loadMoreFail();
    }
    
    // 收起重新整理
    mRefreshLayout.finishLoadmore();
    mRefreshLayout.finishRefresh(0);
    
    // 傳送載入完成的事件
    ...
  }
  
}

Adapter 中

public class MyAdapter extends BaseMultiItemQuickAdapter<Data, BaseViewHolder> {

  public MyAdapter() {
    // 這裡傳入null具體看原始碼
    super(null);
    addItemType(Data.TYPE_STYLE_1, R.layout.item_circle_layout);
  }
  
  // 初始化重新整理
  public void initRefresh(List<Circle> circle) {
    this.mData.clear();
    this.mData.addAll(circle);
    notifyDataSetChanged();
  }
  
  // 初始化重新整理
  public void initRefresh(List<Circle> circle) {
    this.mData.addAll(circle);
    notifyDataSetChanged();
  }  
  
  // 普通10條
  public void refreshDataNotClear(List<Article> data) {
    mData.addAll(0, data);
    notifyDataSetChanged();
  }
  
  // 載入更多
  public void loadMoreData(List<Circle> circle) {
    this.mData.addAll(circle);
    notifyDataSetChanged();
  }

  @Override
  protected void convert(BaseViewHolder helper, Circle item) {
    int viewType = helper.getItemViewType();
    switch (viewType) {
      case Article.TYPE_LK_LANDSCAPE:
        renderBanner(helper, item);
        break;
      case :
        break;
  }
}

實體類

public class New implements MultiItemEntity {
    
    public static final int TYPE_ONE_PIC = 100;

    private int itemType;

    public void setItemType(int itemType) {
        this.itemType = itemType;
    }

    @Override
    public int getItemType() {
        return itemType;
    }
}


相關文章