編輯:Android資訊
之所以要談這個話題是因為你在開發App時可能會發現,Activity擔負的責任非常之重,如果站在MVC框架角度看自己開發的App,一般xml布局文件科Activity的setContentView等充當了View角色,Activity其他代碼充當了Controller角色,其他數據來源(數據庫等)充當了Model角色。所以你會發現Activity違背單一職責原則,負擔過重。同時如果要測試邏輯數據層會發現比較難編寫測試用例。由此來構想,有沒有一種解耦的方法呢?
有,那就是MVP框架。
MVP就是Model-View-Presenter。其實不用做太多解釋,如下圖所示你就能明白大致:

如上圖所示可以看見MVP模式需要具備如下三要素:
看完上面兩段,你可能會疑惑MVP,還有一個MVC,他兩啥關系?
那再來看下MVC吧!
MVC架構
MVC框架認為軟件可以分成如下三個部分:
如下圖很直觀的展示了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代碼下來分析的結果。
完整工程代碼點我進入下載頁面
背景:如下案例模擬一次用戶交互存取數據的過程,用戶輸入數據後點擊保存,然後點擊獲取數據將保存的數據獲取的操作。
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測試代碼。
從AIDL開始談Android進程間Binder通信機制
本文首先概述了Android的進程間通信的Binder機制,然後結合一個AIDL的例子,對Binder機制進行了解析。 概述 我們知道,在Android app中
Android View 自定義 RangeSeekBar 范圍選擇器
前段時間群裡兄弟項目中有類似這樣的需求 我看到兄弟受苦受難,於心不忍。又因事不關己,打算高高掛起。正在愛恨糾結之時,日神對我說:沒事多造點輪子,你的人生會有很多
Android之批量加載圖片OOM問題解決方案
一、OOM問題出現的場景和原因 一個好的app總少不了精美的圖片,所以Android開發中圖片的加載總是避免不了的,而在加載圖片過程中,如果處理不當則會出現OOM
Android平台Airplay的實現方法
如果Android機頂盒能夠支持IOS設備的Airplay協議,實現為Airplay服務器,能夠接收和處理來自IOS設備的多媒體數據(視頻、照片和音樂),將能提高