Android MVP模式初次实践

最近看了一下以前做的项目,想进行对以前项目做一些功能上的改进,但是发现以前的写的的代码由于采用了典型的MVC模式,无论是业务逻辑的处理或者是界面的操作都写在Activity或者Fragment里面,造成代码的阅读和维护性很差,于是决定开始学习一下android mvp模式进行项目的架构的搭建。
首先简单介绍下MVP:
一.什么是MVP?
MVP是模型(Model)、视图(View)、主持人(Presenter)的缩写,分别代表项目中3个不同的模块。
模型(Model):负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等。
视图(View):负责界面数据的显示,与用户进行交互。
主持人(Presenter):相当于协调者,是模型与视图之间的桥梁,将模型与视图分离开来。

  
  
下图是MVP模式与MVC模式的对比图
从上图可知MVC的耦合度还是非常高的,View层可以直接访问Modle层,导致三者之间可以回路。所以我们可以得出MVP与MVC的区别就是:MVP的View层不能直接访问Model层,需要通过Presenter发出请求,View与Model不能直接通信。

二.MVP的优点:
优点:

1.降低耦合度,实现了Model和View真正的完全分离,可以修改View而不影响Modle

2.模块职责划分明显,层次清晰(下面会介绍Bob大叔的Clean Architecture)

3.隐藏数据

4.Presenter可以复用,一个Presenter可以用于多个View,而不需要更改Presenter的逻辑(当然是在View的改动不影响业务逻辑的前提下

5.View可以进行组件化。在MVP当中,View不依赖Model。这样就可以让View从特定的业务场景中脱离出来,可以说View可以做到对业务完全无知。它只需要提供一系列接口提供给上层操作。这样就可以做到高度可复用的View组件。

6.代码的灵活性。

三.将这些理论的东西,我们还不如直接通过做一个登陆的Demo来演示下MVP模式的实例

登陆功能编写后的代码包的结构

1.View层的编写

package hua.com.mvptest2.Login.View;
/**
 * Created by qinghua on 2017/5/24.
 * 登陆View的接口,实现类也就是登陆的LoginActivity
 */

public interface ILoginView {
     void showProgressBar();//显示进度条
     void hideProgressBar();//隐藏进度条
     void setLoginError();//设置登陆错误的效果
     void setLoginSuccess();//设置登陆成功的效果
     void setUserMsgError();//提示登陆用户信息的错误
     void goToMainView();//跳转到主界面
}
package hua.com.mvptest2.Login.View;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import hua.com.mvptest2.Base.BaseActivity;
import hua.com.mvptest2.Bean.User;
import hua.com.mvptest2.Login.Presenter.LoginPresenter;
import hua.com.mvptest2.Main.MainActivity;
import hua.com.mvptest2.R;

public class LoginActivity extends BaseActivity implements ILoginView,View.OnClickListener{

    private ProgressBar mProgressBar;
    private EditText et_userName,et_passWord;
    private Button btn_login;

    private LoginPresenter mPresenter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        initView();
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.btn_login:
                User user=new User();
                user.setUserName(et_userName.getText().toString());
                user.setPassWord(et_passWord.getText().toString());
                mPresenter.attestationServer(user);
                break;
        }
    }

    @Override
    public void initView() {

        mPresenter=new LoginPresenter(this);
        mProgressBar= (ProgressBar) findViewById(R.id.login_progressBar);
        et_userName= (EditText) findViewById(R.id.et_userName);
        et_passWord= (EditText) findViewById(R.id.et_passWord);
        btn_login= (Button) findViewById(R.id.btn_login);
        btn_login.setOnClickListener(this);
    }

    @Override
    public void showToast(String msg) {
        Toast.makeText(this,msg,Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showProgressBar() {
        mProgressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideProgressBar() {
        mProgressBar.setVisibility(View.GONE);
    }

    @Override
    public void setLoginError() {
        showToast(getString(R.string.login_fail));
    }

    @Override
    public void setLoginSuccess() {
        showToast(getString(R.string.login_success));
    }

    @Override
    public void setUserMsgError() {
        showToast(getString(R.string.login_msg_error));
    }

    @Override
    public void goToMainView() {
        Intent intent=new Intent(this, MainActivity.class);
        startActivity(intent);
    }

}

2.Model层的实现:

package hua.com.mvptest2.Login.Model;
import hua.com.mvptest2.Bean.User;
import hua.com.mvptest2.Login.ILoginFinishedListener;

/**
 * Created by qinghua on 2017/5/24.
 * Class Note:模拟登陆的操作的接口
 */

public interface ILoginModel {
    void login(User mUser, ILoginFinishedListener listener);
}
package hua.com.mvptest2.Login.Model;

import android.os.Handler;

import hua.com.mvptest2.Bean.User;
import hua.com.mvptest2.Login.ILoginFinishedListener;

/**
 * Created by qinghua on 2017/5/24.
 */

public class LoginModel implements ILoginModel {
    @Override
    public void login(final User mUser, final ILoginFinishedListener listener) {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if(mUser.getUserName().equals("")||mUser.getPassWord().equals("")){
                    listener.userMsgError();
                }else if(mUser.getUserName().equals("123")&&mUser.getPassWord().equals("123")){
                    listener.loginSuccess();
                }else{
                    listener.loginFail();
                }
            }
        },2000);
    }
}

3.Presenter层的实现:

package hua.com.mvptest2.Login.Presenter;
import hua.com.mvptest2.Bean.User;
/**
 * Created by qinghua on 2017/5/24.
 *  * Class Note:登陆的ILoginPresenter的接口,实现类为LoginPresenter,完成登陆的验证,以及销毁当前view
 */

public interface ILoginPresenter {
    void attestationServer(User user);
    void onDestroy();
}
package hua.com.mvptest2.Login.Presenter;

import hua.com.mvptest2.Bean.User;
import hua.com.mvptest2.Login.ILoginFinishedListener;
import hua.com.mvptest2.Login.Model.ILoginModel;
import hua.com.mvptest2.Login.Model.LoginModel;
import hua.com.mvptest2.Login.View.ILoginView;

/**
 * Created by qinghua on 2017/5/24.
 */

public class LoginPresenter implements ILoginPresenter,ILoginFinishedListener{

    private ILoginModel mLoginModel;
    private ILoginView mLoginView;

    public LoginPresenter(ILoginView mLoginView){
        this.mLoginView=mLoginView;
        mLoginModel=new LoginModel();
    }

    @Override
    public void attestationServer(User user) {
        if(mLoginView!=null){
            mLoginView.showProgressBar();
        }
        mLoginModel.login(user,this);
    }

    @Override
    public void onDestroy() {
        mLoginView=null;
    }

    @Override
    public void loginSuccess() {
        if(mLoginView!=null){
            mLoginView.hideProgressBar();
            mLoginView.setLoginSuccess();
            mLoginView.goToMainView();
        }
    }

    @Override
    public void loginFail() {
        if(mLoginView!=null){
            mLoginView.hideProgressBar();
            mLoginView.setLoginError();
        }
    }

    @Override
    public void userMsgError() {
        if(mLoginView!=null){
            mLoginView.hideProgressBar();
            mLoginView.setUserMsgError();
        }
    }
}

4登陆完成接口的实现:

package hua.com.mvptest2.Login;

/**
 * Created by qinghua on 2017/5/24.
 */

public interface ILoginFinishedListener {
    void loginSuccess();//登陆成功
    void loginFail();//登陆失败
    void userMsgError();//输入的用户登陆信息不完整
}

其他辅助类的实现:

1.BaseActivity

package hua.com.mvptest2.Base;

import android.support.v7.app.AppCompatActivity;

/**
 * Created by qinghua on 2017/5/24.
 */

public abstract class BaseActivity extends AppCompatActivity {
    public abstract void initView();
    public abstract void showToast(String msg);
}

2.User

package hua.com.mvptest2.Bean;
/**
 * Created by qinghua on 2017/5/24.
 */

public class User {
    private String userName;//用户名
    private String passWord;//密码

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
}

作为MVP模式使用的新手,一些接口使用起来确实有绕,但是写完后对代码多思考几遍,还是可以顺利理解的。

作者:周庆华:原文地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值