MVP + SmartRefreshLayout +RecylerView 列表基类的封装(初级版)

前言:

最近在项目中引入了SmartRefreshLayout (github地址)智能刷新控件,支持所有的View(AbsListView,RecyclerView,WebView .... View)和多层嵌套的视图结构。使用更简单,强大。在我们项目中,存在多个下拉刷新的控件(XRecylerView、TwinklingRefreshLayout),效果较混乱,不够统一。代码相似度高,重复代码较多。为了提高代码的复用性、减少重复的代码的编写,将公共的逻辑进行抽取(如设置标题栏、无网络、数据空界面、上拉刷新、下拉加载、设置adapter、设置LayoutManager、设置ItemDecoration等),故初步封装了一个基类。

封装思路:

一、通用列表Activity主要功能分析:

下拉刷新、上拉加载更多、网络异常处理、空数据界面处理、Activity 标题栏设置、返回顶部按钮设置、RecylerView LayoutManager设置、RecylerView Adapter设置、RecylerView ItemDecoration设置。

二、代码编写分析:

抽取公有的代码,父类进行默认实现,子类可以重写定制。减少重复代码的编码,让开发列表界面变得更简单高效。

代码实现:

1、布局代码:

 







    

        
        
        
        
        
        

    

    

        
    

    
    

    
    

    
    

    

2、java代码:

public abstract class BaseListRefreshActivity, T extends RecyclerView.Adapter> extends AppBaseMVPActivity {

private LinearLayout mLlTitleTopRoot, mLlScrollTopRoot, mLlEmptyRoot;
private View mTitleView, mTopFixedView, mTopScrollView, mEmptyView, mNotNetRoot;
private Button mBtnNoNetReload;
private ImageView mImgTop;
private CoordinatorLayout mClContentRoot;
private RecyclerView mRecylerView;
private SmartRefreshLayout mRefreshLayout;
private RecyclerView.ItemDecoration mDefaultItemDecoration;
private RecyclerView.LayoutManager mDefaultLayoutManager;
public Context mContext;
public LayoutInflater mInflater;
private T mAdapter;

public T getAdapter() {
    return mAdapter;
}

public SmartRefreshLayout getSmartRefreshLayout() {
    return mRefreshLayout;
}

public RecyclerView getRecylerView() {
    return mRecylerView;
}

public RecyclerView.ItemDecoration getDefaultItemDecoration() {
    return mDefaultItemDecoration;
}

public RecyclerView.LayoutManager getDefaultLayoutManager() {
    return mDefaultLayoutManager;
}

public View getTitleView() {
    return mTitleView;
}

public View getTopFixedView() {
    return mTopFixedView;
}

public View getTopScrollView() {
    return mTopScrollView;
}

public View getEmptyView() {
    return mTopScrollView;
}

@Override
public int getLayoutResId() {
    return R.layout.activity_base_list_refresht;
}

@Override
public void initData() {
    mContext = this;
    mInflater = LayoutInflater.from(this);
}

@Override
public void initView(Bundle savedInstanceState) {
    findId2View();  // 找到View
    handleTitleTopEmptyView();  // 处理标题栏、空界面View
    handleNotNetReload();  // 处理无网络,重新加载
    handleGoTopClick();  // 处理返回底部按钮的点击事件
    initSmartRefreshLayout();  // 初始化设置SmartRefreshLayout刷新控件
    initRefreshLayoutSetting(mRefreshLayout);  // 提供该方法,方便子类更改SmartRefreshLayout刷新控件的设置
    setDefaultRecylerView(); // 设置RecylerView
    hideGoTopIcon(); // 隐藏返回顶部按钮
    showNormalContentView(); // 显示正常内容的布局
    loadDataFromServer(true); // 请求服务器数据
}

/**
 * 提供初始化布局管理器的方法,子类可重写,默认实现线性布局
 *
 * @return LayoutManager
 */
protected RecyclerView.LayoutManager initLayoutManager() {
    return new LinearLayoutManager(mContext);
}

/**
 * 提供初始化 ItemDecoration的方法,子类可重写,默认实现LinearVerItemDecoration
 *
 * @return RecyclerView.ItemDecoration
 */
protected RecyclerView.ItemDecoration initItemDecoration() {
    return new LinearVerItemDecoration();
}

/**
 * 通过id找到View
 */
private void findId2View() {

    mLlTitleTopRoot = findView(R.id.ll_base_list_refresh_title_root);
    mClContentRoot = findView(R.id.cl_base_list_content_root);
    mLlScrollTopRoot = findView(R.id.ll_base_list_scroll_top_root);
    mRecylerView = findView(R.id.rcy_base_list_recylerView);
    mRefreshLayout = findView(R.id.srl_base_list_refreshLayout);
    mImgTop = findView(R.id.btn_toTop);

    // 设置数据为空时显示的空布局
    mLlEmptyRoot = findView(R.id.ll_base_list_empty_root);

    // 无网络布局
    mNotNetRoot = findView(R.id.view_base_list_no_net_root);
    mBtnNoNetReload = findView(R.id.refresh_again);
}

/**
 * 处理添加标题、顶部View
 */
private void handleTitleTopEmptyView() {
    // 添加 Activity 标题栏
    mTitleView = initTitleView(mInflater, mLlTitleTopRoot);
    if (mTitleView != null) {
        mLlTitleTopRoot.addView(mTitleView);
    }
    // 添加 显示在标题栏下面的View
    mTopFixedView = initTopFixedView(mInflater, mLlTitleTopRoot);
    if (mTopFixedView != null) {
        mLlTitleTopRoot.addView(mTopFixedView);
    }
    // 添加可以随手势上下滑动显隐的View
    mTopScrollView = initTopScrollView(mInflater, mLlScrollTopRoot);
    if (mTopScrollView != null) {
        mLlScrollTopRoot.addView(mTopScrollView);
    }
    // 添加数据为空时显示的空界面
    mEmptyView = initEmptyView(mInflater, mLlEmptyRoot);
    if (mEmptyView != null) {
        mLlEmptyRoot.addView(mEmptyView);
    }
}

/**
 * 初始化标题栏,子类进行实现
 *
 * @param inflater
 * @param titleParent
 * @return
 */
protected abstract View initTitleView(LayoutInflater inflater, LinearLayout titleParent);

/**
 * 初始化 空界面,子类进行实现
 *
 * @param inflater
 * @param emptyParent
 * @return
 */
protected abstract View initEmptyView(LayoutInflater inflater, LinearLayout emptyParent);

/**
 * 网络异常 重新加载按钮点击回调监听方法
 */
protected abstract void onNoNetReload();

/**
 * recylerView 滑动事件回调监听,通常我们返回顶部的按钮的显隐需要用到该方法,子类进行实现
 *
 * @param recyclerView
 * @param dx
 * @param dy
 */

protected abstract void initOnScrolled(RecyclerView recyclerView, int dx, int dy);

/**
 * 初始化Adapter,子类进行实现
 *
 * @return adapter
 */
protected abstract T initAdapter();

/**
 * 从服务器接口加载数据,子类进行实现
 */
protected abstract void loadDataFromServer(boolean isShowProgress);

/**
 * 下拉正在刷新加载回调方法
 *
 * @param refreshlayout
 */
protected abstract void onRefreshing(RefreshLayout refreshlayout);


/**
 * 上拉正在加载更多回调方法
 *
 * @param refreshlayout
 */
protected abstract void onLoadmoreing(RefreshLayout refreshlayout);


/**
 * 初始化 顶部固定栏目View,需要子类重写即可
 *
 * @param inflater
 * @param topParent
 * @return View
 */
protected View initTopFixedView(LayoutInflater inflater, LinearLayout topParent) {
    return null;
}


/**
 * 初始化 顶部可随手势上下移动显隐的栏目View,需要子类重写即可
 *
 * @param inflater
 * @param topScrollParent
 * @return View
 */
protected View initTopScrollView(LayoutInflater inflater, LinearLayout topScrollParent) {
    return null;
}

/**
 * 自定义RefreshLayout设置的方法,子类重新该方法设置即可
 *
 * @param smartRefreshLayout
 */
protected void initRefreshLayoutSetting(SmartRefreshLayout smartRefreshLayout) {

}

/**
 * 初始化 指定刷新的头布局样式
 * 子类需要定制重写该方法
 */
protected RefreshHeader initRefreshHeader() {
    return new ClassicsHeader(mContext).setSpinnerStyle(SpinnerStyle.Translate);//指定为经典Header,默认是 贝塞尔雷达Header
}

/**
 * 初始化 指定刷新的脚布局样式
 * 子类需要定制重写该方法
 */
protected RefreshFooter initRefreshFooter() {
    return new ClassicsFooter(mContext).setSpinnerStyle(SpinnerStyle.Translate); //设置为平移模式
}

/**
 * 初始化 SmartRefreshLayout
 * 1、设置灰色背景
 * 2、设置头布局、脚布局
 * 3、开启滑动底部自动触发加载更多功能
 * 4、设置下拉刷新、上拉加载更多的监听回调
 */
private void initSmartRefreshLayout() {
    mRefreshLayout.setBackgroundResource(R.color.common_light_gray_color);
    mRefreshLayout.setRefreshHeader(initRefreshHeader());
    mRefreshLayout.setRefreshFooter(initRefreshFooter());
    mRefreshLayout.setEnableAutoLoadmore(true);
    mRefreshLayout.setOnRefreshListener(new OnRefreshListener() {
        @Override
        public void onRefresh(final RefreshLayout refreshlayout) {
            onRefreshing(refreshlayout);
        }
    });
    mRefreshLayout.setOnLoadmoreListener(new OnLoadmoreListener() {
        @Override
        public void onLoadmore(final RefreshLayout refreshlayout) {
            onLoadmoreing(refreshlayout);
        }
    });
}

/**
 * 处理网络异常重新加载逻辑
 */
private void handleNotNetReload() {
    mBtnNoNetReload.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // 判断网络是否可用
            if (NetworkUtils.isAvailable(mContext)) {
                onNoNetReload();
                return;
            }
            showToastError("网络异常");
        }
    });
}

/**
 * 处理回顶部按钮点击事件
 */
protected void handleGoTopClick() {
    mImgTop.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mRecylerView.scrollToPosition(0);
        }
    });
}

/**
 * 设置默认单列显示的RecylerView
 */
private void setDefaultRecylerView() {
    mDefaultItemDecoration = initItemDecoration();
    mDefaultLayoutManager = initLayoutManager();
    mAdapter = initAdapter();
    mRecylerView.setLayoutManager(mDefaultLayoutManager);
    mRecylerView.addItemDecoration(mDefaultItemDecoration);
    mRecylerView.setAdapter(mAdapter);
    mRecylerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            initOnScrolled(recyclerView, dx, dy);
        }
    });
}

/**
 * 显示一键回顶部图标
 */
protected void showGoTopIcon() {
    if (mImgTop != null) {
        mImgTop.setVisibility(View.VISIBLE);
    }
}

/**
 * 隐藏一键回顶部图标
 */
protected void hideGoTopIcon() {
    if (mImgTop != null) {
        mImgTop.setVisibility(View.GONE);
    }
}

/**
 * 显示空布局
 */
protected void showEmptyView() {
    mLlEmptyRoot.setVisibility(View.VISIBLE);
    mRefreshLayout.setVisibility(View.GONE);
    mNotNetRoot.setVisibility(View.GONE);
}

/**
 * 显示网络异常布局
 */
protected void showNotNetView() {
    mLlEmptyRoot.setVisibility(View.GONE);
    mRefreshLayout.setVisibility(View.GONE);
    mNotNetRoot.setVisibility(View.VISIBLE);
}

/**
 * 显示正常列表内容的View
 */
protected void showNormalContentView() {
    mRefreshLayout.setVisibility(View.VISIBLE);
    mLlEmptyRoot.setVisibility(View.GONE);
    mNotNetRoot.setVisibility(View.GONE);
  }
}

实践:

1、先上一张效果图

GIF.gif

2、实践代码:
请查看项目中的以下几个类
CommonProdListActivity
ProdListCategoryActivity
ProdListColumnActivity
ProdListCouponActivity
ProdListProDetReduceActivity
ProdListShopCarReduceActivity

小结:

该版本为初级版,代码比较简单,未逐一分析。欢迎大家指正、批评。谢谢!

你可能感兴趣的:(MVP + SmartRefreshLayout +RecylerView 列表基类的封装(初级版))