深入解析MVP怎么玩,接口抽取深入解析

MVP 全称:Model-View-Presenter ;MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。

MVC和MVP的区别?

作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过 Controller。
在MVC里,View是可以直接访问Model的!从而,View里会包含Model信息,不可避免的还要包括一些业务逻辑。 在MVC模型里,更关注的Model的不变,而同时有多个对Model的不同显示,即View。所以,在MVC模型里,Model不依赖于View,但是View是依赖于Model的。不仅如此,因为有一些业务逻辑在View里实现了,导致要更改View也是比较困难的,至少那些业务逻辑是无法重用的。
虽然 MVC 中的 View 的确“可以”访问 Model,但是我们不建议在 View 中依赖 Model,而是要求尽可能把所有业务逻辑都放在 Controller 中处理,而 View 只和 Controller 交互。当然最好是把业务也抽成一个model。

具体怎么写呢?具体请看注释,没提出说明

我们需要写个ViewInterface,ModelInterface以及管理这这两个接口的Presenter类

1、ViewInterface这个是必须的:里面主要定义一些操作界面的方法、结果反馈的方法、UI隐藏的方法,具体方法按照需求划分抽取,主要由activity实现。

2、ModelInterface不是必须的如果业务单一就不需要,如果处理业务需要多个model每一个model都要实现这个公共接口,便于在Presenter中回调,主要由model层实现。

3、Presenter是最重要的是一个普通类,里面定义了一下常量和标志,声明了ViewInterface,ModelInterface两个接口和一个public内部回调接口CallBack。CallBacK主要以匿名接口在Presenter中实现,在实现的方法中可以用ViewInterface回调具体实现的activity的方法。

具体代码如下所示:

ViewInterface代码:

该接口负责定义对view层的所有操作。例如UI更新、view界面数据获取,网络请求成功信息展示、以及界面跳转等各种UI操作。主要供Presenter回调来修改界面,达到控制者的作用,具体方法参数视具体情况而定。

/**
 * 该接口负责定义对view层的所有操作。例如UI更新、view界面数据获取,网络请求成功信息展示、
 * 以及界面跳转等各种UI操作。主要供Presenter回调来修改界面,达到控制者的作用,具体方法参
 * 数视具体情况而定。
 */

public interface LoginViewInterface {

    //获取用户名
    String getUserName();

    //获取密码
    String getUserPassword();
    //展示失败的信息
    void showLoginFailed(String error);

    //展示成功的信息
    void showLoginSuccess(String succ);

    //成功后跳转界面
    void goActivity();

    //展示进度条
    void showProgressBar();

    //取消进度条
    void dismissProgressBar();

    //成功时更新页面
    void updateSuccessUI();

    //失败时更新页面
    void updateFailedUI();
}

activity代码:通过在实现的方法中直接操作界面控件或者获取控件数据,在此就不做实现,主要必须继承ViewInterface

public class Login2Activity extends Activity implements LoginViewInterface {
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        ButterKnife.inject(this);
    }

    @Override
    public String getUserName() {
        return null;
    }

    @Override
    public String getUserPassword() {
        return null;
    }

    @Override
    public void showLoginFailed(String error) {

    }

    @Override
    public void showLoginSuccess(String succ) {

    }

    @Override
    public void goActivity() {

    }

    @Override
    public void showProgressBar() {

    }

    @Override
    public void dismissProgressBar() {

    }

    @Override
    public void updateSuccessUI() {

    }

    @Override
    public void updateFailedUI() {

    }
}

Presenter代码:

内部接口主要是供model层回调,该接口以匿名接口的方式传到model层model回调,里面主要定义一些model对UI界面操作的接口和处理结果的回调,这样能避免大量new对象造成的内存浪费。当然不仅仅可以定义这些方法可以根据需求增加和减少相关方法,将所有业务交给model层,这样就成了真正的MVP模式,如果将业务处理写在Presenter里面,将不是真正的MVP, 
一般情况下接口中和view层接口一一对应,当然也可以一个callback对应多个view接口方法。

public class LoginPresernter {

    private final LoginViewInterface viewInterface;

    private final LoginModelInterface modelInterface;

    private static LoginPresernter mPresernter;

    public static boolean isSuccess=true;

    private LoginPresernter(LoginViewInterface viewInterface){
        this.viewInterface = viewInterface;
        this.modelInterface = new UserLogin();
    }


    public static LoginPresernter getInstance(LoginViewInterface viewInterface){
        if (mPresernter==null){
            mPresernter = new LoginPresernter(viewInterface);
        }
        return mPresernter;
    }

    public void userLogin(){
        String userName = viewInterface.getUserName();
        String userPassword = viewInterface.getUserPassword();
        modelInterface.login(userName, userPassword, new CallBack() {
            /**
             * 通过在匿名接口中回调实现修改实现了VIEW层定义接口的view界面
             * @param string
             */
            @Override
            public void onSuccess(String string) {
                viewInterface.showLoginSuccess(string);
                viewInterface.goActivity();//登录成功的回调
                //当然可以跳转多个界面,不同界面通过做标志判断这样VIEW层业务处理将会极少
            }

            @Override
            public void onFailed(Throwable throwable) {
                viewInterface.showLoginFailed(throwable.getMessage());//登录失败的回调
            }

            @Override
            public void updateUi(Boolean isSuccess) {
                if (isSuccess==LoginPresernter.isSuccess){
                    viewInterface.updateSuccessUI();//更新页面
                }else{
                    viewInterface.updateFailedUI();//更新页面
                }
            }

            @Override
            public void showProgress() {
                viewInterface.showProgressBar();//展示进度条的回调

            }

            @Override
            public void dismissProrgress() {
                viewInterface.dismissProgressBar();//取消进度条的回调的
            }

            @Override
            public void goActivity() {
                viewInterface.goActivity();
            }
        });
    }

    /**
     * 内部接口主要是供model层回调,该接口以匿名接口的方式传到model层供model回调,里面
     * 主要定义一些model对UI界面操作的接口和处理结果的回调,这样能避免大量new对象造成的
     * 内存浪费。当然不仅仅可以定义这些方法可以根据需求增加和减少相关方法,将所有业务交给
     * model层,这样就成了真正的MVP模式,如果将业务处理写在Presenter里面,将不是真正的MVP,
     * 一般情况下接口中和view层接口一一对应,当然也可以一个callback对应多个view接口方法。
     */
    public interface CallBack{
        //成功的回调
        void onSuccess(String string);
        //失败的回调
        void onFailed(Throwable throwable);
        //修改界面的
        void updateUi(Boolean isSuccess);
        //展示进度条
        void showProgress();
        //取消进度条
        void dismissProrgress();
        //界面跳转
        void goActivity();
    }
}

ModeInterface代码:

值得注意的是必须要有Presenter中接口,主要供方法回调,只有一个实现类可以不提供接口,但可读性差,建议都有接口

public interface LoginModelInterface {
    /**
     * 值得注意的是必须要有Presenter中接口,主要供方法回调,只有一个实现类可以不提供接口,但可读性差,建议都有接口
     * @param userName
     * @param userPassword
     * @param callBack
     */
    void login(String userName, String userPassword, LoginPresernter.CallBack callBack);
}

model实现类代码:在model中通过callBack对象将结果返回或者修改界面,

通过Presenter内部接口回调UI方法

public class UserLogin implements LoginModelInterface {
    /** 标识客户端当前是否为后台登录 */
    private boolean mIfBackgroundLogin = true;

    /** 与引擎交互的类 */
    private SysClient mClient = new SysClient();
    /** 记录登录账号的变量 */
    private String mAccount = "";
    /** 记录登录密码的变量 */
    private String mPassword = "";


    @Override
    public void login(String userName, String userPassword, LoginPresernter.CallBack callBack) {
        if (TextUtils.isEmpty(userName.trim())){
            callBack.onFailed(new Throwable("登录账号不能为空!"));
            return;
        }
        if (TextUtils.isEmpty(userPassword.trim())){
            callBack.onFailed(new Throwable("登录密码不能为空!"));
            return;
        }
        mAccount=userName;
        mPassword=userPassword;//这里的数据是从Presenter获得的
        doUserAuth(callBack);
    }


    /**
     * 用户登录认证
     */
    private void doUserAuth(LoginPresernter.CallBack callBack) {
        if (!NetworkHelper.isConnected(UIUtils.getContext())) {
            callBack.onFailed(new Throwable("請打開網絡"));
            return;
        } else {
            userAuth("",callBack);
        }
    }


    private void userAuth(final String param, final LoginPresernter.CallBack callBack) {
        try {
            RequestParams params = null;
            String service = "";
            if (TextUtils.isEmpty(param)) {
                params = mClient.userAuthParam(mAccount, mPassword);
                service = Login.SERVICE;
            } else {
               callBack.onFailed(new Throwable("不支持這種方式登錄哦"));
                return;
            }
            AsyncHttpclient.post(service, params, new TextHttpResponseHandler() {
                @Override
                public void onStart() {
                    callBack.showProgress();//通过Presenter回调UI方法
                }

                @Override
                public void onFailure(int i, Header[] headers, String s, Throwable throwable) {
                    callBack.dismissProrgress();
                    callBack.onFailed(new Throwable("用戶名或密碼錯誤"));
                }

                @Override
                public void onSuccess(int i, Header[] headers, String s) {
                    callBack.dismissProrgress();
                    callBack.onSuccess("登录成功");
                    callBack.goActivity();
                }
            },true);
        }catch (Exception e){

        }
    }
}

这样就一个完美的MVP搭建成功了,至于接口中的方法需要开发者通过需求划分大小,不用太细能满足需求即可。你也可以将业务全部写在Presenter中,这样callBack中就能写一写方法。如果不知道接口里面方法该有那些,请看注释


这是我个人对MVP的一些理解和改进,如果有不对的地方希望高手帮我指出,谢谢。有不懂的也可以评论交流额。









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值