MVP模式

作者: 抽象语法树 | 来源:发表于2018-02-09 20:27 被阅读0次

简介

  • MVP 是从经典的模式MVC演变而来。
  • 在MVC/MVP模式中Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。
  • 但是MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过 Controller。
    MVC模式中三者的关系:


    MVC模式.png

    MVP模式中三者的关系:


    MVP模式.png
  • 事实上,android中的activity就是用到了MVC模式。其中的View对应Activity中与XML文件对应的View控件部分,而Model则对应数据库文件,Sharedprefrence,内存缓冲,磁盘缓冲等数据内容。至于Controller控制层基本上也由Activity层面来进行。
  • 从上面可以看出,在android中,activity同时充当了V和C的角色,使得activity的代码往往会过于臃肿,也不符合“单一职责”的原则,所以MVP模式就出现了。
  • MVP模式出现后Activity就可以只充当V的角色,M对V或者V对M来说几乎是完全透明的,提高了系统的可维护性和扩展性。

实例

  • 接下来通过一个登陆界面来运用MVP模式。
  • ILoginModel即Model的接口:
public interface ILoginModel {

    boolean doLogin(String name,String passwrod);

}

其实就是实现一个向远端服务器验证的功能。

  • LoginModel即ILoginModel的实现类:
public class LoginModel implements ILoginModel{


    @Override
    public boolean doLogin(final String name, final String passwrod) {
        boolean result = false;
        try {
            Thread.sleep(3000);
            result = name.equals(passwrod);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return result;
    }
}

线程睡眠3秒,模拟后台验证的过程。

  • LoginContract封装了View和Presenter的接口:
public interface LoginContract {

    interface LoginView {

        void setPresenter();

        void showLoading();

        void hideLoading();

        void onSuccess();

        void onFail();
    }

    interface LoginPresenter{

        void login(String account, String password);
    }

}

即View需要用的功能是展示加载条,取消加载条,登陆成功的页面显示,登陆失败的页面显示。而Presenter暴露给View的方法则是点击按钮后需要调用的login方法。

  • LoginPresenter即Presenter类,View和Model交接的中转站,负责逻辑的处理。
public class LoginPresenter implements LoginContract.LoginPresenter {

    LoginContract.LoginView mView;
    ILoginModel mModel;

    public LoginPresenter(LoginContract.LoginView mView) {
        this.mView = mView;
        this.mModel = new LoginModel();
    }

    @Override
    public void login(final String account, final String password) {
        mView.showLoading();
        new Thread(new Runnable() {
            @Override
            public void run() {
                final boolean result = mModel.doLogin(account,password);
                Handler handler = new Handler(Looper.getMainLooper());
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (result) {
                            mView.hideLoading();
                            mView.onSuccess();
                        }else {
                            mView.hideLoading();
                            mView.onFail();
                        }
                    }
                });
            }
        }).start();

    }
}

login方法中首先调用View的showLoading()展示加载框,然后新开线程做耗时操作,并通过回调执行对View的其他控制。

  • LoginActivity即View层,负责界面的展示。
public class LoginActivity extends AppCompatActivity implements LoginContract.LoginView{

    private Button mBtLogin;
    private EditText mEtName;
    private EditText mEtPassword;
    private View mLoading;
    LoginContract.LoginPresenter mPresenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        initView();
        setPresenter();
    }

    private void initView() {
        mEtName = (EditText) findViewById(R.id.et_name);
        mEtPassword = (EditText) findViewById(R.id.et_password);
        mBtLogin = (Button) findViewById(R.id.bt_login);
        mLoading = findViewById(R.id.layout_loading);
        mBtLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String name = mEtName.getText().toString();
                String password = mEtPassword.getText().toString();
                mPresenter.login(name,password);
            }
        });
    }

    @Override
    public void setPresenter() {
        mPresenter = new LoginPresenter(this);
    }

    @Override
    public void showLoading() {
        mLoading.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideLoading() {
        mLoading.setVisibility(View.GONE);
    }

    @Override
    public void onSuccess() {
        Toast.makeText(this,"登陆成功",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onFail() {
        Toast.makeText(this,"登陆失败",Toast.LENGTH_SHORT).show();
    }
}

Presenter可通过契约类LoginContract 中View接口定义的方法来对View进行操作。

  • 使用MVP模式后,M和V对互相透明,M和V其中一方的改变都不会影响其他的一方。

总结

  • mvp模式比较适合大型的APP开发,越复杂它的优势越明显,但是如果页面本身很简单,使用MVP模式就会加大工作量,比如上面的登陆界面,明明一个Activity就可以搞定,却被分成了多个接口和类。

相关文章

网友评论

      本文标题:MVP模式

      本文链接:https://www.haomeiwen.com/subject/gwfxtftx.html