国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

細談MVP架構模式

2019-11-09 16:38:44
字體:
來源:轉載
供稿:網友

什么是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是開發過程中非常值得推薦的架構模式,它能夠將各組件進行解耦,并且帶來良好的可擴

展性、可測試性、穩定性、可維護性,同時使得每個類型的職責相對單一、簡單,避免了“臃腫”程序的存在。它的思

想也非常好的提現了面向對象的設計原則,即抽象、單一職責、最小化、低耦合。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 大兴区| 铜鼓县| 韶山市| 临湘市| 合阳县| 潼关县| 谷城县| 泾阳县| 安宁市| 拉孜县| 长春市| 平利县| 武冈市| 乌拉特前旗| 沁阳市| 沂南县| 景洪市| 分宜县| 龙井市| 大兴区| 澄迈县| 道孚县| 秭归县| 广丰县| 甘孜| 仙游县| 隆化县| 达拉特旗| 南木林县| 大渡口区| 土默特左旗| 和硕县| 邢台县| 凌源市| 铜鼓县| 南乐县| 杭锦旗| 大理市| 扶沟县| 怀仁县| 贵定县|