SmartRefreshLayout + BaseRecyclerviewAdapterHelper 使用MVP方式实现下拉刷新

简介: 关键字:SmartRefreshLayout使用 下拉刷新 上拉加载 BaseRecyclerviewAdapterHelper前言下拉刷新和上拉加载是每个APP中最基本的功能,这里将这个功能进行整理。

关键字: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;
    }
}

目录
相关文章
|
2月前
|
JSON 小程序 数据格式
小程序如何实现下拉刷新?
小程序如何实现下拉刷新?
|
5月前
|
前端开发 开发工具 iOS开发
初识MVVM·关于启动页、引导页、登录页的设计细节和交互逻辑(1)
初识MVVM·关于启动页、引导页、登录页的设计细节和交互逻辑
119 0
|
3月前
|
前端开发 JavaScript 定位技术
Flutter vs 前端 杂谈:SliverAppBar、手动实现Appbar、前端Html+JS怎么实现滚动变化型Appbar - 比较
Flutter vs 前端 杂谈:SliverAppBar、手动实现Appbar、前端Html+JS怎么实现滚动变化型Appbar - 比较
33 0
|
5月前
|
JSON 小程序 JavaScript
小程序如何实现下拉刷新
小程序如何实现下拉刷新
201 0
|
5月前
|
前端开发 数据处理 Swift
初识MVVM·关于启动页、引导页、登录页的设计细节和交互逻辑(3)
初识MVVM·关于启动页、引导页、登录页的设计细节和交互逻辑
51 0
|
5月前
|
前端开发 开发工具 iOS开发
初识MVVM·关于启动页、引导页、登录页的设计细节和交互逻辑(2)
初识MVVM·关于启动页、引导页、登录页的设计细节和交互逻辑
27 0
|
Android开发
【安卓开发】借助setOnItemClickListener动态更新Listview
【安卓开发】借助setOnItemClickListener动态更新Listview
113 0
【安卓开发】借助setOnItemClickListener动态更新Listview
|
JavaScript
每日一题:如何实现上拉加载,下拉刷新?
每日一题:如何实现上拉加载,下拉刷新?
252 0
每日一题:如何实现上拉加载,下拉刷新?
|
JavaScript
完整版移动端滑动事件封装
完整版移动端滑动事件封装
257 1
完整版移动端滑动事件封装
【Flutter】ListView 列表高级功能 ( RefreshIndicator 下拉刷新组件 )
【Flutter】ListView 列表高级功能 ( RefreshIndicator 下拉刷新组件 )
382 0
【Flutter】ListView 列表高级功能 ( RefreshIndicator 下拉刷新组件 )