前言:
相信做android开发的都听过mvc和mvp,有的也听过mvvm,不过mvvm现在还不太成熟,而mvc是J2EE开发中使用的,现在使用也用的mvp模式来构建自己的项目,
mvc开发如果项目越来越复杂的话,项目中的actiivty或者fragment代码量也越来越多,这样项目的后期维护也越来越麻烦,在网上可以搜查一下,你会发现现在最适合android开发的构建模式非MVP莫属。
什么是MVP?
MVP是model,view,presenter的缩写,代表了三个不同的模块,
model:用来处理数据的加载或者存储,比如从网络或本地数据库获取数据
view :负责界面数据的展示
presenter:类似于桥梁的功能,是M层和V层的桥梁。
百度一下可得到如下数据:
优点:
1、模型与视图完全分离,我们可以修改视图而不影响模型
2、可以更高效地使用模型,因为所有的交互都发生在一个地方——Presenter 内部
3、我们可以将一个 Presenter 用于多个视图,而不需要改变 Presenter 的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。
4、如果我们把逻辑放在 Presenter 中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)
这样分层的好处就是减少了 Model 与 View 层之间的耦合度。一方面可以使得 View 层和 Model 层单独开发与测试,互不依赖。另一方面 Model 层可以封装复用,可以极大的减少代码量
毕竟一不小心Activity就成为了所谓的上帝类,而mvp避免了activity或者Fragment代码量过多。
接下来我用简单的例子模仿一下mvp模式在项目中的使用,每个人的想法都不一样,我在github上见过有人把activity或者Fragment作为P层去处理的。
项目的结构如图,由于数据都是自己模拟操作的,所以模拟了一下耗时操作,使Demo看起来像联网操作
view层的代码,view层仅仅是负责页面的展示
public interface MainView {
void setData(List users);
void showProgress();
void hideProgress();
void netWorkError();
}
隐藏进度和显示进度,把数据提供给recyclerView
model的代码,m层用来获取数据或者查询数据库的耗时操作,由于是模式数据,所以传一个int值去控制数据的成功或失败
public interface MainModel {
void netWorkMain(int i, MainModelImpl.MainData mainData);
}
public class MainModelImpl implements MainModel {
@Override
public void netWorkMain(final int i, final MainData mainData) {
if (i == 0) {
List list = new LinkedList<>();
for (int j = 0; j < 15; j++) {
list.add("" + j);
}
mainData.onSuccess(list);
} else {
mainData.onError();
}
}
public interface MainData {
void onSuccess(List data);
void onError();
}
}
presenter层持有view和model的对象,在这里P层就是桥梁,而M层和V层就是桥对面居住的人,桥梁搭建好之后双方就可以进行买卖操作,而在代码中,v层就可以获取M层的数据展示在页面上
public interface MainPresenter {
void netWork(int i);
}
public class MainPresenterImpl implements MainPresenter, MainModelImpl.MainData {
private final MainView mainView;
private final MainModel mainModel;
public MainPresenterImpl(MainView mainView) {
this.mainView = mainView;
this.mainModel = new MainModelImpl();
}
@Override
public void netWork(final int i) {
mainView.showProgress();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mainModel.netWorkMain(i, MainPresenterImpl.this);
}
}, 1500);
}
@Override
public void onSuccess(List data) {
mainView.setData(data);
mainView.hideProgress();
}
@Override
public void onError() {
mainView.netWorkError();
mainView.hideProgress();
}
}
然后在activity里面进行一些view的操作
public class MainActivity extends AppCompatActivity implements MainView {
private ProgressBar progressBar;
private List list;
private RecyclerView recyclerView;
private RecyclerViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
progressBar = (ProgressBar) findViewById(R.id.progress);
list = new LinkedList<>();
adapter = new RecyclerViewAdapter(list);
MainPresenter mainPresenter = new MainPresenterImpl(this);
mainPresenter.netWork(0);
recyclerView.setLayoutManager(new StaggeredGridLayoutManager(1, LinearLayoutManager.VERTICAL));
}
@Override
public void setData(List data) {
list.addAll(data);
recyclerView.setAdapter(adapter);
}
@Override
public void showProgress() {
progressBar.setVisibility(View.VISIBLE);
}
@Override
public void hideProgress() {
progressBar.setVisibility(View.GONE);
}
@Override
public void netWorkError() {
Toast.makeText(getApplicationContext(), "失败", Toast.LENGTH_LONG).show();
}
}
这里传的0;model层判断是否是0,然后控制view层显示加载失败还是成功,这里仅仅显示一下成功的操作页面,有兴趣的可以去模拟一下失败。
public class RecyclerViewAdapter extends RecyclerView.Adapter {
private final List data;
public RecyclerViewAdapter(List list) {
this.data = list;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.setData(data.get(position));
}
@Override
public int getItemCount() {
return data.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private final TextView tv;
public ViewHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(R.id.tv);
}
public void setData(String data) {
tv.setText(data);
Log.i("setdat", data);
}
}
}
最终的显示结果:
代码地址:mvpDemo
如果有兴趣的可以去gihub看下我用retrofit和rxjava写的一个小项目,项目是用mvp去构建的。项目的截图:
项目地址:mvp retrofit_rxjava 欢迎star或者 fork