前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >菜鸡的MVP架构漫谈

菜鸡的MVP架构漫谈

作者头像
萬物並作吾以觀復
发布2018-12-19 14:50:55
4540
发布2018-12-19 14:50:55
举报
文章被收录于专栏:指尖下的Android指尖下的Android

相信大家在网上看过关于MVP架构的博客数不胜数,至于MVP到底是什么,也不需要我再从百度百科复制一遍了,通俗的说MVP就是解决Model和View的耦合,没有使用架构的代码就是一个Activity里处理了UI逻辑、网络请求等等,有的时候一个Activity五六百行,我曾经看过同事的一个适配器上千行,因为业务逻辑过于复杂,说了这么多,MVP到底有什么作用呢?我们非用不可吗,MVP可以把"功能"抽离出来,因为一个项目中会出现很多页面的某个功能是相似的,这就代表我们不用架构的话,重复的代码会大量的出现在我们的项目中,这不符合单一原则,最后引用一下大佬的总结,“mvp最关键的点就是把Activity中的ui逻辑抽象成view接口,把业务逻辑抽象成presenter接口,model还是数据模型。架构是对客观不足的妥协,规范是对主观不足的妥协。”

代码语言:javascript
复制
public interface IBaseView {
    void showNetError();
    void showDataError();
    void hideLoading();
    void showLoading();
    void showMsg(String msg);
    Activity getMyContext();
}

基类View

代码语言:javascript
复制
public interface IBasePresenter<T> {
    void attachView(T baseView);
    void detachView();
    boolean isViewAttached();
}

基类Presenter

代码语言:javascript
复制
/**
 * 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

代码语言:javascript
复制
/**
 * 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中去调度呢?

代码语言:javascript
复制
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代码

代码语言:javascript
复制
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);
                    }
                }
            }
        });
    }

}
代码语言:javascript
复制
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);
                    }
                }
            }
        });
    }
}

最开始我的想法是在更新版本的接口上继承更新用户信息的接口,但是后面想想其实可以实现,但是有一个大问题,违背了单一原则,每一个接口仅仅只负责一个功能,如果需要多个功能,那就新建一个接口多继承所需的功能,切记不可让接口继承接口,接口多继承接口,类多实现接口。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.11.29 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档