淺談MVP實現Android應用程式層開發,mvpandroid

來源:互聯網
上載者:User

淺談MVP實現Android應用程式層開發,mvpandroid

PS一句:最終還是選擇CSDN來整理髮表這幾年的知識點,該文章平行遷移到CSDN。因為CSDN也支援MarkDown文法了,牛逼啊!

【工匠若水 http://blog.csdn.net/yanbober】

背景

之所以要談這個話題是因為你在開發App時可能會發現,Activity擔負的責任非常之重,如果站在MVC架構角度看自己開發的App,一般xml布局檔案科Activity的setContentView等充當了View角色,Activity其他代碼充當了Controller角色,其他資料來源(資料庫等)充當了Model角色。所以你會發現Activity違背單一職責原則,負擔過重。同時如果要測試邏輯資料層會發現比較難編寫測試案例。由此來構想,有沒有一種解耦的方法呢?

有,那就是MVP架構。

MVP架構

MVP就是Model-View-Presenter。其實不用做太多解釋,如所示你就能明白大致:

如所示可以看見MVP模式需要具備如下三要素:

程式猿的糾結—MVP與MVC

看完上面兩段,你可能會疑惑MVP,還有一個MVC,他兩啥關係?

那再來看下MVC吧!

MVC架構

MVC架構認為軟體可以分成如下三個部分:

  • 視圖(View):使用者介面。
  • 控制器(Controller):商務邏輯。
  • 模型(Model):資料儲存。

如很直觀的展示了MVC架構的核心:

View傳送指令到Controller,Controller完成商務邏輯後,要求Model改變狀態,Model將新的資料發送到View,使用者得到反饋。

MVP與MVC對比

這時候你會發現MVC與MVP的結構圖都有很大區別,具體區別如下:

MVP架構:

View不直接與Model互動,而是通過與Presenter互動來與Model間接互動。
Presenter與View的互動是通過介面來進行的。
通常View與Presenter是一對一的,但複雜的View可能綁定多個Presenter來處理邏輯。

MVC架構:

View可以與Model直接互動。
Controller是基於行為的,並且可以被多個View共用。
可以負責決定顯示哪個View。

總結

MVC與MVP很相似,但又有很大區別,站在不同分析角度會有不同的觀點,這裡只是站在基於Android App代碼下來分析的結果。

MVP架構的Android應用實戰:

完整工程代碼點我進入下載頁面

背景:如下案例類比一次使用者互動存取資料的過程,使用者輸入資料後點擊儲存,然後點擊擷取資料將儲存的資料擷取的操作。
UI介面:

工程目錄結構:

詳細代碼:

首先看model層代碼,model層提供抽象介面,方便解耦,同時方便測試案例測試model的impl實現代碼。如下展示了抽象介面和實現代碼。

Model層抽象介面:

public interface IInfoModel {    //從資料提供者擷取資料方法    InfoBean getInfo();    //存入資料提供者方法    void setInfo(InfoBean info);}

Model層抽象實現:

public class InfoModelImpl implements IInfoModel {    //類比儲存資料    private InfoBean infoBean = new InfoBean();    @Override    public InfoBean getInfo() {        //類比儲存資料,真實有很多操作        return infoBean;    }    @Override    public void setInfo(InfoBean info) {        //類比儲存資料,真實有很多操作        infoBean = info;    }}

接著看View層代碼,View層同樣提供抽象介面,方便解耦,同時方便測試案例測試View的impl實現互動代碼。如下展示了抽象介面的代碼。

View層的抽象介面:

public interface IInfoView {    //給UI顯示資料的方法    void setInfo(InfoBean info);    //從UI取資料的方法    InfoBean getInfo();}

這個時候其實你可以想想,寫UI和邏輯的人可以完全分工,他們通過介面對接。Presenter的角色更像是一個設計模式的適配器類,負責對接UI與資料邏輯。所以不妨先看下Presenter的實現:

public class Presenter {    private IInfoModel infoModel;    private IInfoView infoView;    public Presenter(IInfoView infoView) {        this.infoView = infoView;        infoModel = new InfoModelImpl();    }    //供UI調運    public void saveInfo(InfoBean bean) {        infoModel.setInfo(bean);    }    //供UI調運    public void getInfo() {        //通過調用IInfoView的方法來更新顯示,設計模式運用        //類似回調監聽處理        infoView.setInfo(infoModel.getInfo());    }}

這時候回過頭看下View層代碼,View層同樣實現了View層提供的抽象介面(也就是Activity類,充當UI View)。

如下展示了View層的實現代碼:

public class MainActivity extends ActionBarActivity implements IInfoView, View.OnClickListener{    private EditText inputId, inputName, inputAddr;    private Button saveBtn, loadBtn;    private TextView infoTxt;    private Presenter presenter;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initData();    }    private void initData() {        presenter = new Presenter(this);        inputId = (EditText) findViewById(R.id.id_input);        inputName = (EditText) findViewById(R.id.name_input);        inputAddr = (EditText) findViewById(R.id.addr_input);        saveBtn = (Button) findViewById(R.id.input_confirm);        loadBtn = (Button) findViewById(R.id.get_confirm);        infoTxt = (TextView) findViewById(R.id.show);        saveBtn.setOnClickListener(this);        loadBtn.setOnClickListener(this);    }    @Override    public void setInfo(InfoBean info) {        StringBuilder builder = new StringBuilder("");        builder.append(info.getId());        builder.append("\n");        builder.append(info.getName());        builder.append("\n");        builder.append(info.getAddress());        infoTxt.setText(builder.toString());    }    @Override    public InfoBean getInfo() {        InfoBean info = new InfoBean();        info.setId(Integer.parseInt(inputId.getText().toString()));        info.setName(inputName.getText().toString());        info.setAddress(inputAddr.getText().toString());        return info;    }    @Override    public void onClick(View v) {        switch (v.getId()) {            case R.id.input_confirm:                presenter.saveInfo(getInfo());                break;            case R.id.get_confirm:                presenter.getInfo();                break;        }    }}

到此解耦並行開發的App編碼工作已經完成,如下展示運行結果:

完整工程代碼點我進入下載頁面

總結

通過上面的例子可以發現,View(Activity)只負責處理使用者互動,並把資料相關的邏輯操作都交給了Presenter去做,而Presenter調用Model處理完資料之後,再通過View的抽象介面更新View顯示的資訊。這樣就實現了完整的解耦UI與邏輯操作。

不過,這種觀點也是站在App局部代碼的角度來分析看待的,對於小型App完全沒這個必要,大型的App和互動複雜的可以考慮這麼處理,既可以解耦,還可以方便編寫test測試代碼。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.