Android MVP与MVC的区别和理解
2016-02-02 本文已影响4666人
Nickyzhang
MVC架构:
MVC就是Model-View-Controller,它们的作用是:
(数据模型)Model:数据的封装和保存,业务逻辑和实体模型
(视图)View:视图界面,对应于布局文件
(控制器)Controller:业务逻辑,对应于Activity、Fragment等
它们之间的关系如下图所示:
View传送指令到Controller,Controller完成业务逻辑后,改变Model的状态,Model将新的数据发送到View,这就是MVC模式的处理逻辑。
MVP架构:
MVP是Model-View-Presenter,它们的作用如下:
Model:业务逻辑和实体模型,用来操作实际的数据,包含Bean和Model的抽象接口来降低耦合。
View:就是Android中的视图,需要建立一个View的抽象接口View Interface。通过实现View的接口来实现View与Presenter的交互,从而降低耦合。对应于Activity,负责View的绘制与用户交互;
Presenter:View和Model的中间枢纽,处理和用户交互的逻辑。
MVP和MVC的对比:
MVP架构:
View不直接与Model交互,而是通过与Presenter交互来与Model间接交互。
Presenter与View的交互是通过接口来进行的。
通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑。
MVC架构:
View可以与Model直接交互。
Controller是基于行为的,并且可以被多个View共享。
可以负责决定显示哪个View。
通过一个简单的例子来理解MVP模式:
View层:
/**
* ViewInterface
* 定义一些通用的view接口
*/
public interface LoadDataView {
/***
* 耗时操作,加载数据,显示Progress
*/
void showLoading();
/***
* 隐藏Progress
*/
void hideLoading();
}
/**
* 更细小的,用来显示图书细节的View接口
*/
public interface LoadBookView extends LoadDataView {
void showDetailsView(BookEntity entity);
}
/***
* Fragment,属于View层,实现了ViewInterface(LoadBookView)
*/
public class BookDetailFragment extends Fragment implements LoadBookView{
/**图书条形码ISBN号*/
public static final String ISBN = "9787121060748";
/**持Presenter对象*/
private BookDetailsPresenter presenter;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initWidget();
presenter = new BookDetailsPresenter(getActivity(), ISBN); // 实例化一个presenter对象
presenter.setView(this); //让Presenter持一个ViewInterface实例(LoadBookView)
presenter.loadData(); //告诉Presenter快给我加载Data
}
@Override
public void showDetailsView(BookEntity entity) {
//更新UI等操作
}
@Override
public void showLoading() {
rlProgress.setVisibility(View.VISIBLE);
}
@Override
public void hideLoading() {
rlProgress.setVisibility(View.GONE);
}
}
2、Presenter层:
public class BookDetailsPresenter {
/**持一个Model层的对象,用来从网页接口Rest Api中提取数据*/
private RestApi restApi = null;
/**一个ViewInterface对象,用来回调Data给View*/
private LoadBookView loadBookView;
private String isbn;
public BookDetailsPresenter(Context context, String isbn) {
restApi = new RestApiImpl(context);
this.isbn =isbn;
}
public void setView(LoadBookView loadBookView) {
this.loadBookView = loadBookView;
}
public void loadData() {
loadBookView.showLoading();
//耗时操作,开个线程异步的加载数据
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
restApi.getBookDetailByIsbn(isbn, bookDetailsCallback);
}
});
thread.start();
}
//匿名内部类,接收bookDetailCallback的回调数据
private RestApi.BookDetailsCallback bookDetailsCallback = new RestApi.BookDetailsCallback() {
@Override
public void onBookEntityLoaded(BookEntity bookEntity) {
notifyDataLoadedSuccessful(bookEntity);
BookDetailsPresenter.this.loadBookView.hideLoading();
}
@Override
public void onError(Exception e) {
//异常后的相关处理
}
};
/***
* 通知获取数据成功了,赶快通知UI更新吧
*/
private void notifyDataLoadedSuccessful(final BookEntity bookEntity) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
BookDetailsPresenter.this.loadBookView.showDetailsView(bookEntity);
}
});
}
}
3、Model层:
/***
* 整个应用程序需要的数据实体类
*/
public class BookEntity {
//一些set,get方法
}
/**
* 一个接口,用来从rest api api获得数据,它的实现在RestApiImpl中
*/
public interface RestApi {
String API_ISBN_BASE_URL = "https://api.douban.com/v2/book/isbn/";
/***
* 更细小的接口,用来将获取到的数据,回调给它的调用者
*/
interface BookDetailsCallback {
void onBookEntityLoaded(BookEntity bookEntity);
void onError(Exception e);
}
/**
* 从网络获取数据,然后通过bookDetailCallback回调给Presenter
* @param isbn
* @param bookDetailsCallback
*/
void getBookDetailByIsbn(final String isbn, final BookDetailsCallback bookDetailsCallback);
}
参考文章:http://www.jianshu.com/p/95c9088eef4f
http://www.codeceo.com/article/mvp-android.html