随着技术的发展,Activity(View) 做的事情越来越多,动辄几百上千行的代码使得 Activity 越来越臃肿。为了更好的划分视图(View)和模型(Model)之间的职责,让 View 只处理数据的展示和用户的交互,把数据的处理交由 Model 处理。
MVP模式可以让显示界面和数据分离,我们开发的应用可以分离至少三层,这样也可以进行独立测试。更加的好维护(代码复用)数据分离有利于信息的隐蔽等等优点,相比较他的优点,缺点就可以忽略了。
下图是采用MVP做的一个列表页面,实现了刷新,加载更多的功能。
view 层的接口 用来与Presenter进行交互
public interface MovieView extends MVPView { void showLoading(); void hideLoading(); void showSwipeRefresh(); void hideSwipeRefresh(); boolean isSwipeRefresh(); void showMovies(List<Movies> movieList); void appendMovies(List<Movies> movieList); void showToast(String content); boolean isTheListEmpty(); }
view 接口的实现类(Activity)
@Override protected void onCreate(BundlesavedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); // 设置 presenter moviePresenter = new MoviePresenter(); moviePresenter.attachView(this); initializeSwipe(); initializeRecycler(); } /** * 初始化SwipeRefreshLayout和设置下拉刷新事件 * */ private void initializeSwipe() { mainSwipe.setColorSchemeResources( android.R.color.holo_blue_light, android.R.color.holo_red_light, android.R.color.holo_orange_light, android.R.color.holo_green_light); mainSwipe.setSize(SwipeRefreshLayout.LARGE); mainSwipe.setProgressViewEndTarget(true, 200); mainSwipe.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { moviePresenter.refresh(); } }); } /** * 初始化RecyclerView * */ private void initializeRecycler() { mainRecyclerView.setLayoutManager(new GridLayoutManager(this, 2)); adaper = new MovieAdaper(); adaper.setRecyclerListListener(this); mainRecyclerView.setAdapter(adaper); mainRecyclerView.setOnScrollListener(recyclerScrollListener); } /*---------省略部分代码--------------*/ /** * 加载更多的判断和触发 * */ private RecyclerView.OnScrollListenerrecyclerScrollListener = new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerViewrecyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); int visibleItemCount = mainRecyclerView.getLayoutManager().getChildCount(); int totalItemCount = mainRecyclerView.getLayoutManager().getItemCount(); int pastVisibleItems = ((GridLayoutManager) mainRecyclerView.getLayoutManager()) .findFirstVisibleItemPosition(); if((visibleItemCount + pastVisibleItems) >= totalItemCount && !moviePresenter.isLoading() && !moviePresenter.isLast()) { moviePresenter.loadMore(); } } };
处理网络请求以及数据分发
package com.jwenfeng.moviemvp.presenters; importandroid.util.Log; importcom.jwenfeng.moviemvp.model.Movies; importcom.jwenfeng.moviemvp.view.MovieView; importjava.util.List; importcn.bmob.v3.BmobQuery; importcn.bmob.v3.listener.FindListener; /** * 当前类注释: * 项目名:MovieMVP * 包名:com.jwenfeng.moviemvp.presenters * 作者:jinwenfeng on 16/4/23 16:38 * 邮箱:823546371@qq.com * QQ: 823546371 * 公司:南京穆尊信息科技有限公司 * © 2016 jinwenfeng * ©版权所有,未经允许不得传播 */ public class MoviePresenter extends Presenter { private MovieViewmovieView; private int limit = 8; // 每页的数据是8条 private int curPage = 0; // 当前页的编号,从0开始 private boolean isLoading = false; private boolean isLast = false; public void attachView(MovieViewmovieView) { this.movieView = movieView; } /** * 获取数据 * */ public void getData() { BmobQuery<Movies> query = new BmobQuery<>(); query.setSkip(curPage * limit); query.setLimit(limit); query.findObjects(movieView.getContext(), new FindListener<Movies>() { @Override public void onSuccess(List<Movies> list) { if (list.size() > 0) { if (movieView.isTheListEmpty()) { movieView.hideLoading(); } if (movieView.isSwipeRefresh()) { movieView.showMovies(list); movieView.hideSwipeRefresh(); } else { Log.e("MoviePresenter",curPage+"----"+list.size()); movieView.appendMovies(list); } curPage++; isLast = false; isLoading = false; } else { isLast = true; isLoading = false; movieView.showToast("没有更多数据了"); } } @Override public void onError(int i, String s) { Log.e("MoviePresenter", i + "---" + s); movieView.showToast("查询失败:" + s); } }); } /** * 加载更多 * */ public void loadMore() { if (!isLast && !isLoading){ isLoading = true; getData(); } } /** * 刷新 * */ public void refresh() { curPage = 0; movieView.showSwipeRefresh(); isLoading = true; getData(); } @Override public void start() { if (movieView.isTheListEmpty()) { movieView.showLoading(); isLoading = true; getData(); } } @Override public void stop() { } public boolean isLoading() { return isLoading; } public boolean isLast() { return isLast; } }
最后的Model就不贴了,就是一个bean
模式没有固定的,适合自己的就是最好的,欢迎关注,不足之处请指教,如果有兴趣可以参考放在GitHub上的源码
github地址: https://github.com/823546371/MovieMVP
本文地址: http://jwenfeng.com/?p=199
尊重原创,转载请注明:From 晓峰残月(http://jwenfeng.com) 侵权必究!