相信大家在网上看过关于MVP架构的博客数不胜数,至于MVP到底是什么,也不需要我再从百度百科复制一遍了,通俗的说MVP就是解决Model和View的耦合,没有使用架构的代码就是一个Activity里处理了UI逻辑、网络请求等等,有的时候一个Activity五六百行,我曾经看过同事的一个适配器上千行,因为业务逻辑过于复杂,说了这么多,MVP到底有什么作用呢?我们非用不可吗,MVP可以把"功能"抽离出来,因为一个项目中会出现很多页面的某个功能是相似的,这就代表我们不用架构的话,重复的代码会大量的出现在我们的项目中,这不符合单一原则,最后引用一下大佬的总结,“mvp最关键的点就是把Activity中的ui逻辑抽象成view接口,把业务逻辑抽象成presenter接口,model还是数据模型。架构是对客观不足的妥协,规范是对主观不足的妥协。”
public interface IBaseView {
void showNetError();
void showDataError();
void hideLoading();
void showLoading();
void showMsg(String msg);
Activity getMyContext();
}
基类View
public interface IBasePresenter<T> {
void attachView(T baseView);
void detachView();
boolean isViewAttached();
}
基类Presenter
/**
* Presenter 基类
* @param <T>
*/
public abstract class BasePresenter<T extends IBaseView> implements IBasePresenter<T> {
private T view;
@Override
public void attachView(T baseView) {
this.view = baseView;
initView();
initModel();
}
abstract void initView();
abstract void initModel();
@Override
public void detachView() {
view = null;
}
@Override
public boolean isViewAttached() {
return view != null;
}
public T getView() {
return view;
}
}
抽象基类Presenter
/**
* Model 回调动作
* @param <T>
*/
public interface OnCallBackModel<T> {
/**
* 请求数据成功时回调动作
* @param datas
*/
void onSuccess(T datas);
/**
* 数据请求成功,由后台返回的code码非成功码调用动作
* @param msg
*/
void onFailure(String msg);
/**
* 网络异常
*/
void onNetError();
/**
* 数据异常
*/
void onDataError();
/**
* 网络请求数据完毕后的执行动作,比如隐藏加载动画
*/
void onComplete();
/**
* 网络请求数据之前,比如开启加载动画
*/
void onBefore();
}
Model的回调接口
以上我自己结合网上博客上的那些MVP博客总结修改的,也是自己在项目中用的,架构比较简单、简陋,但是对于小项目也够用了,也没打算用MVP的开源框架,全自己手写,这里解释下为什么有抽象基类Presenter,因为所有的Presenter都要判断View是否贴上、添加、移除View,这样提取共性比较合适。
在实际的开发过程中,我们可能遇到这种情况,就是一个Activity中需要请求网络判断是否需要更新当前版本和更新用户信息数据,然后另一个Activity也包含了更新用户数据的功能,这样我们就有必要为这个单一的功能抽象出来,那我们怎么在Presenter中去调度呢?
public class AppUpdatePresenter extends BasePresenter<IAppUpdateView> implements IAppUpdatePresenter, IUpdateUserInfoPresenter {
private IAppUpdateModel model;
private IUpdateUserInfoModel userInfoModel;
private IAppUpdateView view;
@Override
public void appUpdate(final String version, String type) {
model.getAppUpdate(version, type, new OnCallBackModel<AppVersionBean>() {
@Override
public void onSuccess(AppVersionBean datas) {
if(isViewAttached()){
view.setAppUpdate(datas);
}
}
@Override
public void onFailure(String msg) {
if(isViewAttached()){
view.showMsg(msg);
}
}
@Override
public void onNetError() {
}
@Override
public void onDataError() {
}
@Override
public void onComplete() {
}
@Override
public void onBefore() {
}
});
}
@Override
public void updateUserInfo(String phone) {
userInfoModel.getUserInfo(phone);
}
@Override
void initView() {
view = getView();
}
@Override
void initModel() {
model = new AppUpdateModel();
userInfoModel = new UpdateUserInfoModel();
}
}
最后再贴上Model代码
public class AppUpdateModel implements IAppUpdateModel {
@Override
public void getAppUpdate(String version, String type, final OnCallBackModel callBackModel) {
Map<String, String> params = new HashMap<>(2);
LogUtils.e("当前版本号------>", version);
params.put("version", version);
params.put("type", type);
HttpManager.postHttp(ConstantUtils.APP_VERSION, params, new StringCallback() {
@Override
public void onError(Call call, Exception e, int id) {
}
@Override
public void onResponse(String response, int id) {
if(StringUtils.isJSONType(response)){
AppVersionBean bean = JsonUtils.fromJson(response, AppVersionBean.class);
if(null == bean){
callBackModel.onFailure(ConstantUtils.DON_NEED_UPDATE);
return;
}
if(bean.getCode().equals(ConstantUtils.DATA_SUCCESS)){
callBackModel.onSuccess(bean);
}else {
callBackModel.onFailure(ConstantUtils.DON_NEED_UPDATE);
}
}
}
});
}
}
public class UpdateUserInfoModel implements IUpdateUserInfoModel{
@Override
public void getUserInfo(String phone) {
Map<String, String> params = new HashMap<>(1);
params.put("mobile", phone);
HttpManager.postHttp(ConstantUtils.CARD_INFO, params, new StringCallback() {
@Override
public void onError(Call call, Exception e, int id) {
}
@Override
public void onResponse(String response, int id) {
if (StringUtils.isJSONType(response)) {
CardInfoBean bean = JsonUtils.fromJson(response, CardInfoBean.class);
if (null == bean) {
return;
}
if (null != bean.getData() && bean.getCode().equals(ConstantUtils.DATA_SUCCESS)) {
User user = AppUtils.getUserData();
CardInfoBean.DataBean datas = bean.getData();
user.setReal_name(datas.getReal_name());
user.setGender(datas.getGender());
user.setPassport_num(datas.getPassport_num());
user.setPassport_status(datas.getPassport_status());
user.setExpire_time(datas.getExpire_time());
user.setId_num(datas.getId_number());
AppUtils.updateUserData(user);
}
}
}
});
}
}
最开始我的想法是在更新版本的接口上继承更新用户信息的接口,但是后面想想其实可以实现,但是有一个大问题,违背了单一原则,每一个接口仅仅只负责一个功能,如果需要多个功能,那就新建一个接口多继承所需的功能,切记不可让接口继承接口,接口多继承接口,类多实现接口。