MVP實現Android應用層開發原理及過程
背景
之所以要談這個話題是因為你在開發App時可能會發現,Activity擔負的責任非常之重,如果站在MVC框架角度看自己開發的App,一般xml佈局檔案科Activity的setContentView等充當了View角色,Activity其他程式碼充當了Controller角色,其他資料來源(資料庫等)充當了Model角色。所以你會發現Activity違背單一職責原則,負擔過重。同時如果要測試邏輯資料層會發現比較難編寫測試用例。由此來構想,有沒有一種解耦的方法呢?
有,那就是MVP框架。
MVP架構
MVP就是Model-View-Presenter。其實不用做太多解釋,如下圖所示你就能明白大致:
如上圖所示可以看見MVP模式需要具備如下三要素:
- 最左側的View。也就是Android中的Activity。同時需要建立一個View的抽象介面View interface。需要View實現的介面,View通過View interface與Presenter進行互動,降低耦合。
- 最右側的Model。用來操做實際資料(譬如資料儲存等)。有時也需要建立一個Model的抽象介面Model interface用來降低耦合。
- 中間的Presenter。作為View與Model互動的中間紐帶,處理與使用者互動的負責邏輯。
程式猿的糾結—MVP與MVC
看完上面兩段,你可能會疑惑MVP,還有一個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測試程式碼。
相關文章
- JWT實現過程及應用JWT
- Android 鍵盤監控的實現原理及過程Android
- Android應用架構之MVP實現Android應用架構MVP
- android開發透過wireshark實現flutter應用抓包AndroidFlutter
- 解析cookie欺騙實現過程及具體應用Cookie
- PHP5 SOAP呼叫原理及實現過程PHP
- Android Protobuf應用及原理Android
- Android應用開發—RecyclerView繪製蒙層AndroidView
- Base64 的原理、實現及應用
- JVM執行原理及Stack和Heap的實現過程JVM
- Android圖片壓縮實現過程及程式碼Android
- 用typescript開發爬蟲過程實踐TypeScript爬蟲
- laravel 應用層執行過程原始碼分析Laravel原始碼
- iOS編譯過程的原理和應用iOS編譯
- Android黑白棋遊戲實現過程及程式碼解析Android遊戲
- JavaScript模板引擎的應用場景及實現原理JavaScript
- Android架構系列-MVP架構的實際應用Android架構MVP
- Android中mmap原理及應用簡析Android
- 驅動開發:透過應用堆實現多次通訊
- Android沉浸式UI實現及原理AndroidUI
- Android 沉浸式 UI 實現及原理AndroidUI
- Android開源mvp專案,實現玩Android客戶端AndroidMVP客戶端
- DNS解析全過程及原理DNS
- Android應用程式程式啟動過程Android
- 布隆過濾器的原理及應用過濾器
- Cookie、Session、JWT在koa中的應用及實現原理CookieSessionJWT
- 外網訪問內網應用原理分析及實現內網
- synchronized的實現原理——鎖膨脹過程synchronized
- HTML5資料推送SSE原理及應用開發HTML
- HTML5簡化移動應用開發過程HTML
- rss在web開發過程中的全方位應用Web
- 基於 MVP 的 Android 元件化開發框架實踐MVPAndroid元件化框架
- [譯] 使用 Architecture Components 開發 MVVM 應用:MVP 開發者的實踐指南MVVMMVP
- HashMap底層實現原理HashMap
- NSDictionary底層實現原理
- AutoreleasePool底層實現原理
- cortex-a8原理實踐及應用
- Vue 3 響應式原理及實現Vue