引言
如果對於mvp和mvc不太熟悉的童鞋,請花一點時間閱讀下面文字內容,純手工打些本人一點粗糙的見解。或者問問度娘多多學習。熟悉者可直接跳過看乾貨,擼代碼階段。
在說mvp之前,相信大家應該都熟悉了mvc(model 、 view 、 control)。在Android的架構中Activity,fragment,佈局的xml相當於View。然而在實際的開發過程中,Android的View層任務太繁重,大家將V和C都糅雜在Activity、Fragment中,這就導致了在實際開發中View層太過累贅,一不小,幾次代碼迭代過後,一個Activity或者Fragment中的代碼就有幾千行,有時候修改個功能在笨重的代碼中摸爬滾打半天才找到關鍵點,對於不熟悉代碼的開發者來說(或者前人編寫代碼質量太低)那代碼迭代接手後簡直是妙不可言。所以將視圖和業務邏輯代碼分開勢在必行。
基於這個現狀,我們偉大的Google粑粑設計了一個更優的框架模式來解決這個問題。就是目前實際開發中火熱的MVP模式(model 、 view 、presenter)。用presenter將model和view隔離開來,一切業務邏輯處理都是通過presenter來進行操作,也就是說presenter是視圖的數據的橋樑,視圖和數據相隔兩端,“可遠觀而不可褻玩”。強制只能使用presenter作爲“郵遞員”來”通信“。
正文
上圖最爲直接,區別:mvc結構,一眼便知,model和view並沒有隔離,view一隻手悄悄的碰到了model層。而mvp中presenter完全壟斷了與數據實體的”貿易“。視圖要數據必須通過presenter。這樣將業務邏輯剝離出去,視圖層專注view的展現。
萬事萬物,有優點就有缺點,偉大的孟子大學者就曾說過”魚與熊掌不可兼得“。
優點:最大的優點剝離了視圖層和業務邏輯層,讓各個類的分工更爲明確,邏輯更爲清晰,代碼擴展性更高,後期代碼迭代更新更加容易,同時也方便了單元測試的編寫,以前將視圖與業務混合在一起的時候,要寫單元測試很多時候真的是無從下手。相對於MVP模式來說寫單元測試就更加容易了。因爲職責更加清晰,測試的目標就明確多了。
缺點:相對而言,MVP模式的代碼量就多了,類文件也多了,簡單的一個業務邏輯操作就要各方來配合協作(即是需要presenter 和 view的接口)。但是這個問題完全在可以接收的範圍。完全符合Java的抽象封裝設計原則(接口隔離,開閉原則,里氏代換不熟悉的童鞋闊以問問偉大的度娘)。
代碼結構
首先是View和presenter的接口,抽象出view對象的綁定方法。
IView.java
public interface IView {
void bindView();
void UnbindView();
}
IPresenter.java
public interface IPresenter {
void register(V view);
void unRegister();
}
BasePresenter實現IPresenter接口,爲業務邏輯層presenter的基類。用弱引用來接收View的對象,在取消註冊的時候銷燬view對象,保證View不會造成內存泄漏。
BasePresenter.java
public class BasePresenter implements IPresenter {
protected WeakReference iView;
@Override
public void register(V view) {
Log.i(TAG, "BasePresenter register: ");
iView = new WeakReference(view);
}
@Override
public void unRegister() {
Log.i(TAG, "BasePresenter unRegister: ");
iView.clear();
}
}
BaseActivity實現IView接口,爲視圖層的基類(也就是Activity的基類),這是一個抽象類,實現了視圖層到業務邏輯層的綁定與解綁,抽象方法createPresenter()子類必須實現,來確保不通的業務邏輯層。
BaseActivity.java
public abstract class BaseActivity
extends Activity implements IView{
protected P iPresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bindView();
}
@Override
protected void onDestroy() {
super.onDestroy();
UnbindView();
}
@Override
public void bindView() {
iPresenter = createPresenter();
iPresenter.register(this);
}
@Override
public void UnbindView() {
iPresenter.unRegister();
}
protected abstract P createPresenter();
}
接下來是具體的使用MVP的流程了,定義三方交接接口
public interface DemoContract {
interface View{
void demoView(String test);
}
interface Presenter{
void demoPresenter();
}
interface Model{
void demoModel(ModelListener modelListener);
interface ModelListener{
void completed(String test);
}
}
}
視圖層DemoActivity.java基層BaseAcitivity實現createPresenter()方法,DemoContract.View接口。
public class DemoActivity extends BaseActivity implements DemoContract.View {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iPresenter.demoPresenter();
}
@Override
protected DemoPresenter createPresenter() {
return new DemoPresenter();
}
@Override
public void demoView(String test) {
Toast.makeText(this, test, Toast.LENGTH_LONG).show();
}
}
業務邏輯層DemoPresenter.java基層BasePresenter實現DemoContract.Presenter接口
public class DemoPresenter extends BasePresenter implements DemoContract.Presenter {
DemoContract.Model model = new DemoModel();
@Override
public void demoPresenter() {
model.demoModel(new DemoContract.Model.ModelListener() {
@Override
public void completed(String test) {
iView.get().demoView(test);
}
});
}
}
數據實體層DemoModel.java實現DemoContract.Model接口,用接口回調異步返回數據。
public class DemoModel implements DemoContract.Model{
@Override
public void demoModel(ModelListener modelListener) {
modelListener.completed("mvp test");
}
}