一个符合MVP设计要求,且具备上拉刷新功能的RecyclerView

先看一下UML简图:

接下来是代码:

首先来看一下Presenter:

public class Presenter1 {

    ViewLayer1 mViewLayer;
    Recycler1Module mRecyclerModule = new Recycler1Module();

    public Presenter1(ViewLayer1 viewLayer) {
        this.mViewLayer = viewLayer;
        /**
         * 设置加载更多的监听回调
         */
        mViewLayer.setOnNeedLoadListener(new OnNeedLoadListener() {

            @SuppressWarnings("static-access")
            @Override
            public void loadMore(int from, int length) {
                mRecyclerModule.loadMore(from, length,
                        new OnDataLoadedListener() {
                            @Override
                            public void onDataLoaded(
                                    final List<AppCardViewBean> cardViewBeanList) {
                                // 加载更多成功
                                mViewLayer.showMoreContent(cardViewBeanList);
                                mViewLayer
                                        .setLoadStatusNrefreshFooter(LoadStatus.DRAG_UP_TO_LAOD_MORE);
                            }

                            @Override
                            public void onDataLoadFailed(Throwable e) {
                                // 加载更多失败
                                Toast.makeText(
                                        mViewLayer.getInnerView().getContext(),
                                        "未能读取到数据", 0).show();
                                // mViewLayer.showError(e);
                                mViewLayer.showLoadMoreFailure();
                                mViewLayer
                                        .setLoadStatusNrefreshFooter(LoadStatus.DRAG_UP_TO_LAOD_MORE);
                            }
                        });

            }
        });
    }

    /**
     * 方法名要改
     */
    public void onActivityCreate() {
        /**
         * 初始化module
         */
        // mModule = new Module1();
        loadData(0, Constance.ITEM_IN_A_PAGE);// 这个时候加载第一页
    }

    void onActivityDestroyed() {
        // TODO 目前什么都不做
    }

    /**
     * 在界面初始化的时候调用这个方法 这个方法会根据情况让显示层显示loading,content或者error
     * 
     * @param pageNum
     *            暂时还没用到
     */
    @SuppressWarnings("static-access")
    void loadData(int from, int length) {
        mViewLayer.showLoading();
        // load data from module and let view show them

        mRecyclerModule.loadMore(from, length, new OnDataLoadedListener() {

            @Override
            public void onDataLoaded(
                    final List<AppCardViewBean> cardViewBeanList) {
                // 第一次加载成功
                // 点击事件
                mViewLayer.showFirstPageContent(cardViewBeanList,
                        new RecyclerViewOnClickListener() {

                            @Override
                            public void onItemClicked(View view, int position) {
                                Intent intent = new Intent(
                                        UiUtils.getContext(),
                                        AppDetailActivity.class);
                                intent.putExtra("app_name", "position:"+position);
                                UiUtils.startActivity(intent);
                                
                            }
                        });
                

            }

            @Override
            public void onDataLoadFailed(Throwable e) {
                // 第一次加载失败
                Toast.makeText(mViewLayer.getInnerView().getContext(),
                        "未能读取到数据", 0).show();
                mViewLayer.showError(e);
            }
        });

        

    }
public interface OnDataLoadedListener {
        void onDataLoaded(List<AppCardViewBean> cardViewBeanList);

        void onDataLoadFailed(Throwable e);
    }
}

接下来看ViewLayer:

 

public class ViewLayer1 {
    
    private PullUpRecyclerController mRecyclerController;
    private View mView;
    private TextView mErrorTextView;
    private ProgressBar mProgressBar;
    Context context;
    SwipeRefreshLayout mSwipRefreshLayout;

    public ViewLayer1(Context context) {
        this.context = context;
       
        LayoutInflater inflater = LayoutInflater.from(context);
        mView = inflater.inflate(R.layout.frag1layout, null);

        RecyclerView recyclerView = (RecyclerView) mView
                .findViewById(R.id.recyclerView);
        mRecyclerController = new PullUpRecyclerController(context,
                recyclerView);

        mErrorTextView = (TextView) mView.findViewById(R.id.errorView);
        mProgressBar = (ProgressBar) mView.findViewById(R.id.loadingView);
        mSwipRefreshLayout = (SwipeRefreshLayout) mView
                .findViewById(R.id.contentView);
        /**
         * 目前没有下拉的逻辑
         */
        mSwipRefreshLayout.setOnRefreshListener(new OnRefreshListener() {

            @Override
            public void onRefresh() {

                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mSwipRefreshLayout.setRefreshing(false);
                    }
                }, 1200);

            }
        });
    }

    /**
     * 第一次showContent之前一定要先调用这个方法
     * 
     * @param mOnNeedLoadListener
     */
    public void setOnNeedLoadListener(OnNeedLoadListener mOnNeedLoadListener) {
        mRecyclerController.setOnNeedLoadListener(mOnNeedLoadListener);
    }

    

    public View getInnerView() {
        // return mListView;
        // return mSwipRefreshLayout;
        return mView;
    }

    public void showLoading() {
        mErrorTextView.setVisibility(View.INVISIBLE);
        mSwipRefreshLayout.setVisibility(View.INVISIBLE);
        mProgressBar.setVisibility(View.VISIBLE);
    }

    /**
     * 在显示第一页的时候调用,之后就没再调用了
     * 
     * @param beanList
     * @param onclickListener
     */
    public void showFirstPageContent(List<AppCardViewBean> beanList,
            RecyclerViewOnClickListener onclickListener) {
        mErrorTextView.setVisibility(View.INVISIBLE);
        mProgressBar.setVisibility(View.INVISIBLE);
        mSwipRefreshLayout.setVisibility(View.VISIBLE);

        mRecyclerController.showFirstpageItems(beanList);
        mRecyclerController.setOnItemClickListener(onclickListener);
        
    }

    public void showError(Throwable e) {
        mSwipRefreshLayout.setVisibility(View.INVISIBLE);
        mProgressBar.setVisibility(View.INVISIBLE);
        mErrorTextView.setVisibility(View.VISIBLE);
    }

    public void showMoreContent(List<AppCardViewBean> cardViewBeanList) {
        mRecyclerController.showMoreItems(cardViewBeanList);
    }

    public void setLoadStatusNrefreshFooter(LoadStatus clickLoadMore) {
        mRecyclerController.setLoadStatusNrefreshFooter(clickLoadMore);
    }

    /**
     * 加载更多未获取到数据时调用此方法,目前留空
     */
    public void showLoadMoreFailure() {
        
    }
}

接下来是PullUpRecyclerController:

public class PullUpRecyclerController {
    private RecyclerView mRecyclerView;
    private RecyclerAdapter1 mAdapter;
    private int mLastVisibleItemPosition = 0;
    private LinearLayoutManager mLayoutManager;
    
    private Context mContext;

    private OnNeedLoadListener mOnNeedLoadListener;

    public PullUpRecyclerController(Context context, RecyclerView recyclerView) {
        onCreate(context, recyclerView);
    }

    protected void onCreate(Context context, RecyclerView recyclerView) {
        mContext = context;
        
        mRecyclerView = recyclerView;
        mLayoutManager = new LinearLayoutManager(context);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        
    }

    public View getRecyclerView() {
        return mRecyclerView;
    }

    /**
     * 构造方法已经调用此方法 当想要更换listener时再调用此方法
     * 
     * @param listener
     */
    public void setOnNeedLoadListener(OnNeedLoadListener listener) {
        this.mOnNeedLoadListener = listener;
    }

    public interface OnNeedLoadListener {
        public void loadMore(int from, int length);
    }

    /**
     * 第一次显示recyclerView的时候调用的方法。
     * 
     * @param list
     */
    @SuppressWarnings("deprecation")
    public void showFirstpageItems(List<AppCardViewBean> list) {
        mAdapter = new RecyclerAdapter1(mContext, list);
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setOnScrollListener(new OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView,
                    int newState) {

                super.onScrollStateChanged(recyclerView, newState);
                if (newState == RecyclerView.SCROLL_STATE_IDLE
                        && mLastVisibleItemPosition + 1 == mAdapter
                                .getItemCount()) {
                    if (mOnNeedLoadListener != null) {
                        /**
                         * 在调用回调接口前,要先确定是否已经在回调了 没有在回调的话,还要更新footer
                         */
                        if (Recycler1Module.isLoadingMore) {
                            return;
                        }
                        Recycler1Module.isLoadingMore = true;
                        setLoadStatusNrefreshFooter(LoadStatus.LOADING_MORE);

                        /**
                         * 调用回调接口
                         */
                        mOnNeedLoadListener.loadMore(mAdapter.getItemCount(),
                                Constance.ITEM_IN_A_PAGE);
                    }
                    
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

                super.onScrolled(recyclerView, dx, dy);
                mLastVisibleItemPosition = mLayoutManager
                        .findLastVisibleItemPosition();
            }
        });

    }

    /**
     * 显示更多条目 应该先调用showFirstpageItems方法
     * 
     * @param list
     */
    public void showMoreItems(List<AppCardViewBean> list) {
        mAdapter.addAllNRefresh(list);
    }

    /**
     * 调用adapter的同名方法 并暴露给ViewLayer
     * 
     * @param clickLoadMore
     */
    public void setLoadStatusNrefreshFooter(LoadStatus clickLoadMore) {
        mAdapter.setLoadStatusNrefreshFooter(clickLoadMore);
    }
    
    /**
     * 要再showFirstPageItems之后调用此方法
     * @param listener
     */
    public void setOnItemClickListener(RecyclerViewOnClickListener listener){
        mAdapter.setOnItemClickListener(listener);
    }
}

接下来是RecyclerAdapter:

public class RecyclerAdapter1 extends RecyclerView.Adapter<ViewHolder> {
    private static final int VIEW_TYPE_FOOTER = 0;
    private static final int VIEW_TYPE_ITEM = 1;
    private List<AppCardViewBean> mList;
    private LayoutInflater mInflater;
    private Context mContext;
    private LoadStatus mLoadStatus = LoadStatus.DRAG_UP_TO_LAOD_MORE;
    private RecyclerViewOnClickListener mOnItemClickListener;
    
    
    private Recycler1Module mForData = new Recycler1Module();

    public RecyclerAdapter1(Context context, List<AppCardViewBean> list) {
        this.mContext = context;
        mInflater = LayoutInflater.from(context);
        this.mList = list;
    }

    @Override
    public int getItemCount() {
        return mList.size() + 1;
    }

    @Override
    public int getItemViewType(int position) {
        if (position + 1 == getItemCount()) {// 最后一条数据
            return VIEW_TYPE_FOOTER;
        } else {
            return VIEW_TYPE_ITEM;
        }
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        switch (getItemViewType(position)) {
        case VIEW_TYPE_FOOTER:
            onBindFooterViewHolder(holder, position, mLoadStatus);
            break;
        case VIEW_TYPE_ITEM:
            onBindItemViewHolder(holder, position);
            break;
        default:
            break;
        }
    }

    private void onBindFooterViewHolder(ViewHolder holder, int position,
            LoadStatus mLoadStatus2) {
        FooterViewHolder viewHolder = (FooterViewHolder) holder;
        switch (mLoadStatus2) {
        case DRAG_UP_TO_LAOD_MORE:
            viewHolder.mLoadingLayout.setVisibility(View.GONE);
            viewHolder.mClickLoad.setVisibility(View.VISIBLE);
            break;
        case LOADING_MORE:
            viewHolder.mLoadingLayout.setVisibility(View.VISIBLE);
            viewHolder.mClickLoad.setVisibility(View.GONE);
            break;
        case LOAD_FAILED:
            break;
        case LOAD_END:
            break;
        }
    }

    private void onBindItemViewHolder(ViewHolder holder, int position) {
        ItemViewHolder viewHolder = (ItemViewHolder) holder;
        
        viewHolder.cardView.setAppName(mList.get(position).getAppName());
        viewHolder.cardView.setSizeText(mList.get(position).getAppSize());
        viewHolder.cardView.setBriefDesc(mList.get(position).getBriefDesc());
    }

    // ===================onCreateHolder below==================
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == VIEW_TYPE_FOOTER) {
            return onCreateFooterViewHolder(parent, viewType);
        } else if (viewType == VIEW_TYPE_ITEM) {
            return onCreateItemViewHolder(parent, viewType);
        } else {
            return null;
        }
    }

    private ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
        
        AppMainCardView view = new AppMainCardView(mContext);
        return new ItemViewHolder(view, mOnItemClickListener);
    }

    private ViewHolder onCreateFooterViewHolder(ViewGroup parent, int viewType) {
        View view = mInflater.inflate(R.layout.item_footer, null);
        return new FooterViewHolder(view);
    }

    /**
     * 普通item的条目的holder
     * 
     * @author administrator1
     * 
     */
    class ItemViewHolder extends RecyclerView.ViewHolder {
        
        private AppMainCardView cardView;

        private RecyclerViewOnClickListener mListener;

        public ItemViewHolder(View view, RecyclerViewOnClickListener listener) {
            super(view);
            cardView = (AppMainCardView) view;
            this.mListener = listener;
            view.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    if (mListener != null) {
                        mListener.onItemClicked(v, getPosition());// 应该用getlayoutposition?

                    }

                }
            });
            
        }

    }

    class FooterViewHolder extends RecyclerView.ViewHolder {
        public LinearLayout mLoadingLayout;
        public TextView mClickLoad;

        public FooterViewHolder(View itemView) {
            super(itemView);
            mLoadingLayout = (LinearLayout) itemView.findViewById(R.id.loading);
            mClickLoad = (TextView) itemView.findViewById(R.id.click_load_txt);
            mClickLoad.setOnClickListener(new View.OnClickListener() {// 添加点击加载更多监听
                        @Override
                        public void onClick(View v) {
                            
                        }
                    });
        }

    }

    // ===========================method about data=========
    /**
     * 唯一的实现刷新效果的,就这两行语句实现刷新效果
     * 
     * @param list
     */
    public void addAllNRefresh(List<AppCardViewBean> list) {
        this.mList.addAll(list);
        notifyDataSetChanged();
    }

    public void reSetData(List<AppCardViewBean> list) {
        this.mList = list;
        notifyDataSetChanged();
    }

    /**
     * 设置Adapter的状态并且刷新footer 被controller调用
     * 
     * @param status
     */
    public void setLoadStatusNrefreshFooter(LoadStatus status) {
        this.mLoadStatus = status;
        this.notifyItemChanged(getItemCount() - 1);
    }

    public enum LoadStatus {
        DRAG_UP_TO_LAOD_MORE, // 点击加载更多
        LOADING_MORE, // 正在加载更多
        LOAD_FAILED, LOAD_END
    }

    /**
     * 设置点击事件
     * @param listener
     */
    public void setOnItemClickListener(@NonNull RecyclerViewOnClickListener listener) {
        mOnItemClickListener = listener;
    }

}

module的代码就不贴了

 

最后是在fragment中的使用:

public class Fragment1 extends BaseFragment{
    Presenter1 mPresenter;
    ViewLayer1 mViewLayer;

    @Override
    @Nullable
    public View onCreateView(LayoutInflater inflater,
            @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mViewLayer = new ViewLayer1(this.getContext());
        mPresenter = new Presenter1(mViewLayer);

        mPresenter.onActivityCreate();
        return mViewLayer.getInnerView();
    }
}

 

posted @ 2017-08-17 18:03  BlogCommunicator  阅读(289)  评论(0编辑  收藏  举报