Android MVP模式

  • 什么是MVP模式

  • MVP跟MVC的区别

  • MVP模式在Android里的应用

什么是MVP模式

  M : Model
  V : View
  P : Presenter
  MVP把Activity中的UI逻辑抽象成View接口,把业务逻辑抽象成Presenter接口,Model类还是原来的Model。
 
  Model负责数据的处理,View负责页面的展示,而Presenter则负责完成View与Model之间的逻辑跟交互,Presenter的出现可以将View和Model完全独立开,在android开发中的体现就是activity仅用于显示界面和交互,不参与模型结构和逻辑
借用一张图:(来自鸿洋的博客)
MVP

MVP跟MVC的区别

  在说区别之前先解释下什么是耦合性(百度):
  耦合性(Coupling),也叫耦合度,是对模块间关联程度的度量。耦合的强弱取决于模块间接口的复杂性、调用模块的方式以及通过界面传送数据的多少。
  我们写代码心中也会一直叨叨着低耦合,高聚合,MVP的出现确实让我们的代码耦合度降低。犊子扯完,接下来简述MVP跟MVC的区别:
  借用一张图(来自:这里):
  MVP跟MVC的区别
  在MVC中,View可以直接访问Model,但是Model不依赖于View,所以View不可避免要进行大量的逻辑处理跟数据交互,这样想要去修改View是十分费事费力的,而在Android中Activity充当了View+Controll的角色,所以当一个页面复杂的时候一个Activity的代码会有几千行,这样维护的成本会非常高。
  在MVP中,Presenter完全将View跟Model进行了分离,Presenter跟具体的View是没有直接联系的,而是通过定义好的接口进行交互,这样我们可以保持View在变化的同时Presenter不变,在View中有Presenter的引用,在Presenter中持有对于View跟Model的interface引用,整个工作流程如下:
  MVP工作流程

MVP模式在Android里的应用

  我用MVP模式写了一个注册的简单Demo来演示MVP模式在Android中的应用:
  目录结构
  MVPDemo
  
  效果演示
  效果演示
  
  需求分析

Created with Raphaël 2.1.0 注册开始 输入用户名 用户名是否正确 输入密码 密码格式是否正确 确认密码 两次密码是否一致 注册成功,跳转成功页面展示信息 yes no yes no yes no

  流程非常简单:代码实现如下

  View需要进行的操作

public interface IRegisterView {
    void clearState();//清除输入错误提示

    void showProgress();//显示进度条

    void hideProgress();//隐藏进度条

    void hideKeyboard();//隐藏键盘

    String getUserName();//获取输入框输入的用户名

    String getPassword();//获取输入框输入的密码

    String getConfirmPassword();//获取输入框输入的确认密码

    TextInputLayout getNameWrapper();//获取TextInputLayout用来显示错误信息
    TextInputLayout getPasswordWrapper();//获取TextInputLayout用来显示错误信息
    TextInputLayout getConfirmPasswordWrapper();//获取TextInputLayout用来显示错误信息

    void navigateToSuccessPage(User user);//跳转到注册成功的页面
}

  
  View的具体实现
  

public class RegisterActivity extends AppCompatActivity implements IRegisterView {
    private Button registerBtn;
    private TextInputLayout nameWrapper, passwordWrapper, passwordConfirmWrapper;
    private RegisterPresenter registerPresenter;
    private ProgressDialog mProgressDialog;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.register_layout);
        registerBtn = (Button) findViewById(R.id.btn_register);
        nameWrapper = (TextInputLayout) findViewById(R.id.input_name_wrapper);
        passwordWrapper = (TextInputLayout) findViewById(R.id.input_password_wrapper);
        passwordConfirmWrapper = (TextInputLayout) findViewById(R.id.input_password_confirm_wrapper);
        registerBtn.setOnClickListener(mOnclickListener);
        registerPresenter = new RegisterPresenter(this);
        mProgressDialog = new ProgressDialog(this);
        mProgressDialog.setMessage("注册中,请稍后...");
    }

    private final View.OnClickListener mOnclickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
           registerPresenter.register();
        }
    };


    @Override
    public void clearState(){
        if(nameWrapper != null){
            nameWrapper.setErrorEnabled(false);
        }
        if(passwordWrapper != null){
            passwordWrapper.setErrorEnabled(false);
        }
        if(passwordConfirmWrapper != null){
            passwordConfirmWrapper.setErrorEnabled(false);
        }

    }

    @Override
    public void showProgress() {
        if(mProgressDialog != null && !mProgressDialog.isShowing()){
            mProgressDialog.show();
        }
    }

    @Override
    public void hideProgress() {
        if(mProgressDialog != null && mProgressDialog.isShowing()){
            mProgressDialog.dismiss();
        }
    }

    @Override
    public void hideKeyboard() {
        Utils.hideKeyboard(this);
    }

    @Override
    public String getUserName() {
        if(nameWrapper != null) {
            return nameWrapper.getEditText().getText().toString();
        }
        return null;
    }

    @Override
    public String getPassword() {
        if(passwordWrapper != null){
            return passwordWrapper.getEditText().getText().toString();
        }
        return null;
    }

    @Override
    public String getConfirmPassword() {
        if(passwordConfirmWrapper != null){
            return passwordConfirmWrapper.getEditText().getText().toString();
        }
        return null;
    }

    @Override
    public TextInputLayout getNameWrapper() {
        return nameWrapper;
    }

    @Override
    public TextInputLayout getPasswordWrapper() {
        return passwordWrapper;
    }

    @Override
    public TextInputLayout getConfirmPasswordWrapper() {
        return passwordConfirmWrapper;
    }

    @Override
    public void navigateToSuccessPage(User user) {
        Intent mIntent = new Intent(this,MainActivity.class);
        mIntent.putExtra("user",user);
        startActivity(mIntent);
    }


}

  Model需要进行的操作

public interface IRegisterModel {
    void saveUser(String userName,String userPwd,onRegisterFinishedListener onRegisterFinishedListener);//存储用户信息

    User getUser();//获取用户信息

    interface onRegisterFinishedListener{//需要Presenter来实现这个接口对注册结果进行处理
        void registerSuccess(User user);
        void registerFailed();
    }
}

  Model具体操作

public class RegisterModelImp implements IRegisterModel {
    User mUser ;

    @Override
    public void saveUser(String userName, String userPwd, onRegisterFinishedListener onRegisterFinishedListener) {
        if(userName != null && userPwd != null){
            mUser = new User(userName,userPwd);
            onRegisterFinishedListener.registerSuccess(mUser);
        }else{
            onRegisterFinishedListener.registerFailed();
        }
    }

    @Override
    public User getUser() {
        return mUser;
    }
}

  Presenter的操作

public class RegisterPresenter implements IRegisterModel.onRegisterFinishedListener{

    IRegisterView iRegisterView;
    IRegisterModel registerModel;


    public RegisterPresenter(IRegisterView iRegisterView){
        this.iRegisterView = iRegisterView;
        registerModel = new RegisterModelImp();
    }


    public void register(){
        iRegisterView.clearState();
        if(Utils.isEmptyName(iRegisterView.getUserName())){
            iRegisterView.getNameWrapper().setError("用户名不能为空");
        }else if(!Utils.invalidPassword(iRegisterView.getPassword())){
            iRegisterView.getPasswordWrapper().setError("密码长度不得低于6位");
        }else if(!Utils.invalidConfirmPassword(iRegisterView.getPassword(), iRegisterView.getConfirmPassword())){
            iRegisterView.getConfirmPasswordWrapper().setError("两次密码输入不一致");
        }else{
            doRegister(iRegisterView.getUserName(), iRegisterView.getPassword());
        }

    }

    /**
     * 立即注册
     */
    private void doRegister(final String userName, final String userPwd){
        iRegisterView.hideKeyboard();
        iRegisterView.showProgress();
        Handler mHandler = new Handler();
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                iRegisterView.hideProgress();
                registerModel.saveUser(userName,userPwd,RegisterPresenter.this);
            }
        },2000);
    }


    @Override
    public void registerSuccess(User user) {//注册成功
        iRegisterView.navigateToSuccessPage(user);
    }

    @Override
    public void registerFailed() {//注册失败
        //TODO
    }
}

  Bean(由于需要传输Bean所以实现了Parcelable接口)

public class User implements Parcelable{

    private int userId;
    private String name;
    private String password;
    public User(){}

    public User(String name,String password){
        this.name = name;
        this.password = password;
    }

    public User(Parcel parcel){
        userId = parcel.readInt();
        name = parcel.readString();
        password = parcel.readString();
    }
    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "UserName = "+this.getName()+"\nUserPassword = "+this.getPassword();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(userId);
        dest.writeString(name);
        dest.writeString(password);
    }

    public static final Parcelable.Creator<User> CREATOR = new Parcelable.Creator<User>(){

        @Override
        public User createFromParcel(Parcel source) {
            return new User(source);
        }

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };
}

  登录成功展示的页面

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        Intent resultIntent = getIntent();
        if(resultIntent != null){
            TextView mTextView = (TextView)findViewById(R.id.tv_register_result);
            User mUser = resultIntent.getParcelableExtra("user");
            if(mUser != null){
                mTextView.setText(mUser.toString());
            }

        }
    }
个人总结: 为什么要使用MVP?

  1,提高代码维护性
  2,代码清晰
  3,项目结构清晰
  最后:如果APP业务逻辑比较简单的话完全没有必要去使用MVP,不要为了使用MVP而使用MVP,一切都是以业务的复杂度来取舍

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值