什么是MVP架構?:
MVP就是Model-View-PResenter,MVP是從經典的模式MVC演變而來,它們的基本思想有相通的地方:
Controller/Presenter負責邏輯的處理,Model提供數據,View負責顯示。作為一種新的模式,MVP與MVC有著一個
重大的區別:在MVP中View并不直接使用Model,它們之間的通信是通過Presenter (MVC中的Controller)來進行的,
所有的交互都發生在Presenter內部,而在MVC中View會直接從Model中讀取數據而不是通過 Controller。在MVC里,
View是可以直接訪問Model的!從而,View里會包含Model信息,不可避免的還要包括一些業務邏輯。在MVC模型里,
更關注的Model的不變,而同時有多個對Model的不同顯示,及View。所以,在MVC模型里,Model不依賴于View,
但是View是依賴于Model的。不僅如此,因為有一些業務邏輯在View里實現了,導致要更改View也是比較困難的,
至少那些業務邏輯是無法重用的。用流程圖的方式解釋就更清楚了:

MVP和MVC的區別,及MVP是如何解決MVC的問題?
MVP架構:
View: 對應于Activity,負責View的繪制以及與用戶交互
Model: 依然是業務邏輯和實體模型
Presenter: 負責完成View于Model間的交互

View不直接與Model交互,而是通過與Presenter交互來與Model間接交互。
Presenter與View的交互是通過接口來進行的。
通常View與Presenter是一對一的,但復雜的View可能綁定多個Presenter來處理邏輯。
MVC架構:
View:對應于布局文件
Model:業務邏輯和實體模型
Controllor:對應于Activity

View可以與Model直接交互。
Controller是基于行為的,并且可以被多個View共享。
可以負責決定顯示哪個View。
總結解釋一下就是說:
從MVC到MVP的一個轉變,就是減少了Activity的職責,減輕了它的負擔,簡化了Activity中的代碼和一些操作,
將邏輯代碼提取到了Presenter中進行處理,降低了其耦合度。
MVP的優點
1.降低耦合度,隱藏數據,Activity中代碼更簡潔
2.模塊職責劃分明顯3.方便測試驅動開發4.代碼復用度較高5.代碼靈活性
基于MVP架構編寫代碼:
我們來先看下目錄層:這里用展示一個列表數據為例。

1.View層:
MainActivity.java:public class MainActivity extends AppCompatActivity implements MvpView {    private ListView listview;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        listview = (ListView) findViewById(R.id.lv);        //需要通過某種方式獲取數據源        new MainAcPresenter(this).setModel(1).load();    }    @Override    public void showData(List<String> list) {        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);        listview.setAdapter(arrayAdapter);    }}MvpView.java界面接口,這個接口封裝的方法基本上都跟視圖展示有關。public interface MvpView {    public void showData(List<String> list);//更新界面得有數據源}2.model層:MvpModel.java封裝的方法基本上是跟取數據相關的操作
public interface MvpModel {    void getData(onLoadCompleteListener onLoadCompleteListener);    interface  onLoadCompleteListener{        void onLoadComplete(List<String> list);    }}MainModel2.java:	public class MainModel2 implements MvpModel {    @Override    public void getData(onLoadCompleteListener onLoadCompleteListener) {        //這里方式變了        List<String> list = new ArrayList<>();        for (int i = 0; i < 100; i++) {            list.add("這是更新后的數據"+i+"條");        }        onLoadCompleteListener.onLoadComplete(list);    }}MainAcModel.java:public class MainAcModel implements MvpModel {    @Override    public void getData(onLoadCompleteListener onLoadCompleteListener) {        List<String> list = new ArrayList<>();        for (int i = 0; i < 100; i++) {            list.add("這是第" + i + "條數據");        }        if(onLoadCompleteListener !=null){            onLoadCompleteListener.onLoadComplete(list);        }    }}這里寫了兩個model是為了演示一個界面中取數據的兩種不同方式。3.presenter層(核心):
MainAcPresenter.java:Presenter是Model和View之間交互的橋梁,里面有一些業務邏輯的操作。public class MainAcPresenter {    private MvpView mvpView;    private MvpModel mvpModel;    public MainAcPresenter(MvpView mvpView) {        this.mvpView = mvpView;        this.mvpModel = new MainAcModel();    }    public MainAcPresenter setModel(int model) {        switch (model) {            case 0:                mvpModel = new MainAcModel();                break;            case 1:                mvpModel = new MainModel2();                break;        }        return this;    }    public void load() {        mvpModel.getData(new MvpModel.onLoadCompleteListener() {            @Override            public void onLoadComplete(List<String> list) {			//調用MainActivity中的showData()方法,并將list集合傳到activity中。                mvpView.showData(list);	            }        });    }}上面代碼的整體思路就是:將頁面的顯示與數據的獲取解耦,在沒用mvp模式之前,都是將數據獲取和界面邏輯全部
寫在activity中,這樣導致了代碼結構不清晰,不容易去維護。MVP的核心就是將數據的獲取與界面邏輯分離,通過第
三者Presenter去講兩者關聯起來,進而相應的業務邏輯(數據+界面顯示)集中于presenter層中,如果一個項目由三個
人做,就可以按此模塊分工開發,寫界面的去關注界面模塊,進行數據操作的就只關注數據操作模塊,寫業務邏輯的
人員也可以專注于業務邏輯,這樣子分工就很明確,并且也不會互相影響。
但是同時上面的代碼依然存在著問題,還不能用于實際開發中。因為Presenter經常性地需要執行一些耗時操作,例如請求網絡數據。而presenter持有了MainActivity的強引用,如果
在請求結束之前Activity被銷毀了,那么由于網絡請求還沒有返回,導致presenter一直持有MainActivity對象,使得
MainActivity對象無法被回收,此時就發生了內存泄漏。
那我們該如何解決這樣的問題呢?我們的答案是,通過弱引用和Activity或者fragment的聲明周期來解決這個問題。首先建立一個presenter抽象,我們命
名為BasePresenter,它是一個泛型類。
public class BasePresenter<V extends MvpView> {    private WeakReference<V> weakReference;			//view接口類型的弱引用    public void attach(V mvpView) {        weakReference = new WeakReference(mvpView);	//建立關聯    }    public void deAttch() {        if (weakReference != null) {            weakReference.clear();            weakReference = null;        }    }    public V getView() {        return weakReference.get();    }		public boolean isViewAttached(){		return weakReference!=null && weakReference.get()!=null;	}}BasePresenter有4個方法,分別與view建立關聯、解除關聯、判讀是否與view建立了關聯、獲取view.View類型通過BasePresenter的泛型類型傳遞過來,Presenter對這個View持有弱引用,通常情況下這個View類型應該是實現了某個
特定接口的Activity或者Fragment等類型。
MainAcPresenter修改如下:
public class MainAcPresenter extends BasePresenter<MvpView> {    private MvpModel mvpModel;    public MainAcPresenter() {        mvpModel = new MainAcModel();    }    public MainAcPresenter setModel(int model) {        switch (model) {            case 0:                mvpModel = new MainAcModel();                break;            case 1:                mvpModel = new MainModel2();                break;        }        return this;    }    public void load() {        mvpModel.getData(new MvpModel.onLoadCompleteListener() {            @Override            public void onLoadComplete(List<String> list) {                getView().showData(list);            }        });    }}創建一個BaseActivity基類,通過這個基類的聲明周期函數來控制它與presenter的關系。public abstract class BaseActivity<V extends MvpView,T extends BasePresenter<V>> 	extends AppCompatActivity{    public T basePresenter;    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        basePresenter = getBasePresenter();        basePresenter.attach((V) this);//最終的this代表具體的子類,子類在繼承的時候就必須實現MvpView    }    @Override    protected void onDestroy() {        super.onDestroy();        basePresenter.deAttch();    }    public abstract T getBasePresenter();}BaseActivity含有兩個泛型參數,第一個是View接口類型,第二個是presenter的具體類型。通過泛型參數,使得一些通用的邏輯可以被抽象到BaseActivity類中。例如,在BaseActivity的onCreate函數中,會通過getBasePresenter()函數
創建一個具體的presenter,這個presenter的類型就是BasePresenter<T>類型。構建Presenter之后調用attachView函
數與Activity建立關聯。而在onDestory函數中,則會與Activity解除關聯,從而避免內存泄漏。有人會問,如果在
onDestory中解除了對Activity的引用,那么久沒有必要再用弱引用了,但是并不是任何情況下Activity的onDestroy方法
都會被調用,一旦這種情況發生了,弱引用也能夠保證不會造成內存泄漏。
view層中的MainActivity修改如下:
public class MainActivity extends BaseActivity<MvpView,MainAcPresenter> 	implements MvpView{    private ListView listview;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        listview = (ListView) findViewById(R.id.lv);        //需要通過某種方式獲取 數據源        basePresenter.setModel(1).load();    }    @Override    public MainAcPresenter getBasePresenter() {        return new MainAcPresenter();    }    @Override    public void showData(List<String> list) {        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,list);        listview.setAdapter(arrayAdapter);    }}此時,presenter的創建以及與view建立關聯等操作都被封裝到BaseActivity中,消除了子類重復代碼的同時又避免了Activity的內存泄漏問題。可以為Fragment、FragmentActivity等類型都建立一個類似這樣的基類。大總結:
從整體效果來看,MVP是開發過程中非常值得推薦的架構模式,它能夠將各組件進行解耦,并且帶來良好的可擴
展性、可測試性、穩定性、可維護性,同時使得每個類型的職責相對單一、簡單,避免了“臃腫”程序的存在。它的思
想也非常好的提現了面向對象的設計原則,即抽象、單一職責、最小化、低耦合。
新聞熱點
疑難解答