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); }