Android MVP 实例运用
2016-04-26 本文已影响1185人
晓峰残月
Android MVP介绍
随着技术的发展,Activity(View) 做的事情越来越多,动辄几百上千行的代码使得 Activity 越来越臃肿。为了更好的划分视图(View)和模型(Model)之间的职责,让 View 只处理数据的展示和用户的交互,把数据的处理交由 Model 处理。
在MVP模式里通常包含4个要素:
- View:负责绘制UI元素、与用户进行交互(在Android中体现为Activity);
- View interface:需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试;
- Model:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合);
- Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。
![](https://img.haomeiwen.com/i1448227/1210143e95311451.png)
Android MVP 好处
MVP模式可以让显示界面和数据分离,我们开发的应用可以分离至少三层,这样也可以进行独立测试。更加的好维护(代码复用)数据分离有利于信息的隐蔽等等优点,相比较他的优点,缺点就可以忽略了。
Android MVP 实例
下图是采用MVP做的一个列表页面,实现了刷新,加载更多的功能。
![](https://img.haomeiwen.com/i1448227/e28226b7c177087c.jpg)
目录结构
![](https://img.haomeiwen.com/i1448227/fb5c364ca7f2b887.png)
View 层
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(Bundle savedInstanceState) {
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.OnScrollListener recyclerScrollListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, 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();
}
}
};
Presenter
处理网络请求以及数据分发
package com.jwenfeng.moviemvp.presenters;
import android.util.Log;
import com.jwenfeng.moviemvp.model.Movies;
import com.jwenfeng.moviemvp.view.MovieView;
import java.util.List;
import cn.bmob.v3.BmobQuery;
import cn.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 MovieView movieView;
private int limit = 8; // 每页的数据是8条
private int curPage = 0; // 当前页的编号,从0开始
private boolean isLoading = false;
private boolean isLast = false;
public void attachView(MovieView movieView) {
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
最后的Model就不贴了,就是一个bean
模式没有固定的,适合自己的就是最好的,欢迎关注,不足之处请指教,如果有兴趣可以参考放在GitHub上的源码
github地址:https://github.com/823546371/MovieMVP
本文地址:http://www.jianshu.com/p/6c883af5cabb
尊重原创,转载请注明:From 晓峰残月(http://jwenfeng.com) 侵权必究!