概述
對(duì)于MVP設(shè)計(jì)模式,是目前為止, Android開(kāi)發(fā)中最為流行也被證實(shí)最為有效的設(shè)計(jì)模式,其它一些設(shè)計(jì)架構(gòu)很多都是以MVP為基礎(chǔ)的。
本篇博客是MVP在實(shí)際工作中深入應(yīng)用的總結(jié),不是MVP的入門博客,對(duì)于入門讀者請(qǐng)點(diǎn)擊下面的傳送裝置:
對(duì)于MVP,我就在實(shí)際工作中遇到的場(chǎng)景,進(jìn)行總結(jié)
場(chǎng)景一 : 多個(gè)地方有相同操作
相同的操作,既可以指同一功能,也可以指完成某件事情的一系列操作。
例如:

對(duì)于 每一個(gè)列表項(xiàng)的商品,都有“關(guān)注”的功能。其它的地方也有“關(guān)注”功能,那么該如何處理呢?
在降價(jià)通知中的商品也有“關(guān)注”的功能

分析
對(duì)于每一個(gè)商品,我們發(fā)現(xiàn),“關(guān)注”功能是基本的功能,每一個(gè)地方都是存在的,那么我們應(yīng)該把該功能模塊抽象出來(lái),進(jìn)行模塊化,這個(gè)能力應(yīng)該是每一個(gè)coder都可以想到的。
問(wèn)題是該如何抽象出來(lái)?因?yàn)檫@里面包含了業(yè)務(wù)代碼和相關(guān)的界面操作代碼。
看看mvp在這個(gè)模塊部分的工作。
code過(guò)程
首先建立一個(gè) FocusContract
public interface FocusContract {
interface View {
void showProgressDialog(String message);
void showProgressDialog();
void hideProgressDialog();
void showToast(String message);
void showToast(int resId);
}
interface Presenter {
interface FocusChangeResultListener{
void result(boolean result);
}
void addFocus(int goodsId, FocusChangeResultListener listener);
void removeFocus(int goodsId, FocusChangeResultListener listener);
}
}
然后,我創(chuàng)建 一個(gè)FoucsPresenter 實(shí)現(xiàn) Contract.Presenter接口 ,來(lái)模擬業(yè)務(wù)接口。
public class FoucsPresenter implements FocusContract.Presenter {
private FocusContract.View mView;
private Handler mHandler = new Handler();
public FoucsPresenter( FocusContract.View view) {
mView = view;
}
@Override
public void addFocus(final int goodsId, @NonNull final FocusChangeResultListener listener) {
//模擬業(yè)務(wù)過(guò)程
mView.showProgressDialog("正在添加關(guān)注");
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
listener.result(true);
mView.hideProgressDialog();
mView.showToast("添加成功");
}
},5000);
}
@Override
public void removeFocus(final int goodsId,@NonNull final FocusChangeResultListener listener) {
mView.showProgressDialog("正在移除關(guān)注");
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
listener.result(true);
mView.hideProgressDialog();
mView.showToast("移除成功");
}
},5000);
}
實(shí)現(xiàn)Contract.View的相關(guān)接口
public class FocusView implements FocusContract.View {
private CustomProgressDialog mProgressDiaog;
private Toast mToast;
private Activity mActivity;
public FocusView(Activity activity){
mProgressDiaog = new CustomProgressDialog(activity);
mActivity = activity;
}
public void showToast(String message){
if (mToast != null){
mToast.cancel();
}
mToast = Toast.makeText(mActivity,message,
Toast.LENGTH_SHORT);
mToast.show();
}
public void showToast(int resId){
if (mToast != null ){
mToast.cancel();
}
mToast = Toast.makeText(mActivity,resId,
Toast.LENGTH_SHORT);
mToast.show();
}
@Override
public void showProgressDialog(String message) {
if (!mProgressDiaog.isShowing()) {
mProgressDiaog.show(message);
}
}
@Override
public void showProgressDialog() {
mProgressDiaog.show();
}
@Override
public void hideProgressDialog() {
mProgressDiaog.dismiss();
}
}
為了使用方便,我對(duì) View 和present進(jìn)行再次的封裝
public class FocusManger {
private FocusContract.View mView;
private FocusContract.Presenter mPresenter;
public interface OnFocusListener {
void succeed(int goodsId);
void failure(int goodsId);
}
public FocusManger(Activity activity) {
mView = new FocusView(activity);
mPresenter = new FoucsPresenter(mView);
}
public void addFoucs(final int goodsId, final OnFocusListener listener) {
mPresenter.addFocus(goodsId, new FocusContract.Presenter.FocusChangeResultListener() {
@Override
public void result(boolean result) {
mView.hideProgressDialog();
if (result) {
listener.succeed(goodsId);
} else {
listener.failure(goodsId);
}
}
});
}
public void removeFocus(final int goodsId, final OnFocusListener listener) {
mPresenter.removeFocus(goodsId, new FocusContract.Presenter.FocusChangeResultListener() {
@Override
public void result(boolean result) {
mView.hideProgressDialog();
if (result) {
listener.succeed(goodsId);
} else {
listener.failure(goodsId);
}
}
});
}
}
于是碰到 添加關(guān)注的這一功能,要是用的時(shí)候就非常的簡(jiǎn)單了,只需要如下的代碼:
FocusManger focusManger = new FocusManger(context)
focusManger.addFoucs(goodsIdTag, new FocusManger.OnFocusListener() {
@Override
public void succeed(int goodsId) {
}
@Override
public void failure(int goodsId) {
}
});
總結(jié)
看到?jīng)],經(jīng)過(guò)上面步驟,我使用mvp的設(shè)計(jì)架構(gòu)將這個(gè)“關(guān)注”的相關(guān)的操作進(jìn)行了封裝。這樣在任何界面碰到關(guān)注這個(gè)功能的手就可以直接使用,少寫(xiě)了大量的代碼。
最重要的是,采用上面的方式,具有良好的擴(kuò)展性,有有一天業(yè)務(wù)變了,取消了“關(guān)注”這個(gè)功能,那么我只需要改動(dòng)幾行代碼就行了,有一關(guān)注功能的業(yè)務(wù)邏輯改變了,那么我只需要更換相應(yīng)的 業(yè)務(wù)邏輯代碼就行了,界面部分不需要任何改動(dòng)。
場(chǎng)景二
如果一個(gè) Fragment 或者 Activity 的界面復(fù)雜,功能較多,那么建議使用多個(gè) presenter 和 View 也就是說(shuō)進(jìn)行切分。