美文网首页
MVP + SmartRefreshLayout +Recyle

MVP + SmartRefreshLayout +Recyle

作者: 幸福的拾荒者_ | 来源:发表于2017-08-15 16:36 被阅读0次

    前言:

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

    封装思路:

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

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

    二、代码编写分析:

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

    代码实现:

    1、布局代码:

     <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    
    <!--设置activity Title标题-->
    <LinearLayout
        android:id="@+id/ll_base_list_refresh_title_root"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"/>
    
    <android.support.design.widget.CoordinatorLayout
        android:id="@+id/cl_base_list_content_root"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
    
        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:fitsSystemWindows="true"
            app:elevation="2dp">
    
            <!--可以跟随上下滑动显示隐藏的头部局-->
            <!--scroll|snap 滑动到顶部才显示出来-->
            <!--app:layout_scrollFlags="scroll|snap"-->
            <!--scroll|enterAlways|snap 往上滑就显示出来-->
            <!--app:layout_scrollFlags="scroll|enterAlways|snap"-->
            <LinearLayout
                android:id="@+id/ll_base_list_scroll_top_root"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/common_white_color"
                android:orientation="vertical"
                app:layout_scrollFlags="scroll|enterAlways|snap"/>
    
        </android.support.design.widget.AppBarLayout>
    
        <com.scwang.smartrefresh.layout.SmartRefreshLayout
            android:id="@+id/srl_base_list_refreshLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            app:srlEnableHeaderTranslationContent="true"
            app:srlEnableLoadmore="true"
            app:srlEnableRefresh="true">
    
            <android.support.v7.widget.RecyclerView
                android:id="@+id/rcy_base_list_recylerView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/common_white_color"
                />
        </com.scwang.smartrefresh.layout.SmartRefreshLayout>
    
        <!--添加右下角一键置顶按钮-->
        <include layout="@layout/inc_to_top"/>
    
        <!--网络异常的界面-->
        <include
            android:id="@+id/view_base_list_no_net_root"
            layout="@layout/common_no_net_layout"
            android:visibility="gone"/>
    
        <!--未有数据加载为空显示的空界面-->
        <LinearLayout
            android:id="@+id/ll_base_list_empty_root"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@color/common_white_color"
            android:orientation="vertical"
            android:visibility="gone"/>
    
        </android.support.design.widget.CoordinatorLayout>
    </LinearLayout>
    

    2、java代码:

    public abstract class BaseListRefreshActivity<V extends BaseView, P extends BasePresenter<V>, T extends RecyclerView.Adapter> extends AppBaseMVPActivity<V, P> {
    
    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 +Recyle

          本文链接:https://www.haomeiwen.com/subject/lhnprxtx.html