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
