Android架构设计之MVP模式

MVP基本概念

MVP(Model-View-Presenter)是从MVC的演变过来的,MVP的角色定义:

  • 模型层(Model):主要是获取数据功能,业务逻辑和实体模型。
  • 视图层(View):对应于Activity或Fragment,负责视图的部分展示和业务逻辑用户交互
  • 控制层(Presenter):负责完成View层与Model层间的交互,通过P层来获取M层中数据后返回给V层,使得V层与M层间没有耦合。

在MVP中 ,Presenter层完全将View层和Model层进行了分离,把主要程序逻辑放在Presenter层实现,Presenter与具体的View层(Activity)是没有直接的关联,是通过定义接口来进行交互的,从而使得当View层(Activity)发生改变时,Persenter依然可以保持不变。View层接口类只应该只有set/get方法,及一些界面显示内容和用户输入,除此之外不应该有多余的内容。绝不允许View层直接访问Model层,这是与MVC最大区别之处,也是MVP核心优点。
这里写图片描述

MVP基本使用

项目目录结构主要分为三部分,分别是:model、view、presenter;其中model目录存放bean类、网络异步访问的接口及实现类和网络访问的回调接口,view目录对应的是Activity和View层接口,presenter层:对应的是presenter类。下面以一个简单的登录例子:
这里写图片描述

Model层:和MVC中M层是一样的,主要是定义网络请求接口(LoginModel)并实现接口(LoginModelImpl )然后通过接口的回调(LoginListener)把数据结果返回给P层,从而达到M层与V层间没有交互,是通过P层把结果返回给V层的,这与MVC是有所不同的是,在MVC中会直接把M层的数据返回到V层。

/**
 * desc: 用户信息实体类
 */

public class UserInfo {

    private String userName;

    private String sex;

    public String getUserName() {
        return userName;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}
/**
 * desc:Login数据层的实现类
 */

public class LoginModelImpl implements LoginModel<UserInfo>{

    @Override
    public void getUserInfo(String userName, String pwd, LoginListener<UserInfo> listener) {

        UserInfo userInfo = new UserInfo();
        userInfo.setUserName(userName);
        //下面是模拟网络访问结果的调用
        listener.onStart_();
        if (!TextUtils.isEmpty(userName) && !TextUtils.isEmpty(pwd)){
            listener.onSuccess(userInfo);
        }else {
            listener.onFailed();
        }
        listener.onFinish();

    }


}
/**
 * desc: login-Model
 */

public interface LoginModel<T>{

    void getUserInfo(String userName, String pwd, LoginListener<T> listener);
}
/**
 * desc:登录回调监听
 */

public interface LoginListener<T> {

    /*请求前一些准备,比如加载提示等待*/
    void onStart_();

    /*访问成功调用*/
    void onSuccess(T t);

    /*访问失败*/
    void onFailed();

    /*访问结束*/
    void onFinish();

}

Presenter层:在Presenter类中有Model层和View层接口的实例,必须初始化了这两个实例才可以调用getUserData方法达到V层与M层的数据交互。


/**
 * desc: Presenter层,通过P层来获取M层的数据,同时把数据返回给V层
 *       P层相当于V层与M层间中间桥梁,两者间的交互必须通过P层来完成
 *       不允许直接访问。
 */

public class LoginPresenter {

    private LoginModelImpl mLoginModel;

    private LoginView<UserInfo> mLoginView;

    public LoginPresenter(LoginModelImpl loginModel, LoginView<UserInfo> loginView) {
        mLoginModel = loginModel;
        mLoginView = loginView;
    }


    public void getUserData(String userName,String pwd){
        mLoginModel.getUserInfo(userName, pwd, new LoginListener<UserInfo>() {
            @Override
            public void onStart_() {
                mLoginView.showLoading();
            }

            @Override
            public void onSuccess(UserInfo userInfo) {
                mLoginView.showLoginSuccess(userInfo);
            }

            @Override
            public void onFailed() {
                mLoginView.showLoginFailed();
            }

            @Override
            public void onFinish() {
                mLoginView.hideLoading();
            }
        });
    }
}

View层:V层是不能直接与M层进行交互的,必须通过接口的方式实现交互。

/**
 * desc:定义View层接口,实现与Presenter层间交互
 */

public interface LoginView<T> {

    /*显示dialog*/
    void showLoading();

    /*隐藏dialog*/
    void hideLoading();

    /*登录成功的处理操作,比如保存用户信息,跳转界面……*/
    void showLoginSuccess(T t);

    /*登录失败的提示*/
    void showLoginFailed();
}
public class MainActivity extends AppCompatActivity implements LoginView<UserInfo> {

    private EditText mEtName;
    private EditText mEtPassword;
    private Button mButLogin;
    private ProgressDialog mProgressDialog;

    private LoginModelImpl mLoginModel;
    private LoginPresenter mLoginPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mEtName = findViewById(R.id.et_user_name);
        mEtPassword = findViewById(R.id.et_password);
        mButLogin = findViewById(R.id.but_login);

        mProgressDialog=new ProgressDialog(this);
        mProgressDialog.setTitle("请求中……");

        //
        mLoginModel= new LoginModelImpl();
        mLoginPresenter=new LoginPresenter(mLoginModel,this);

        mButLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //登录
                String userName = mEtName.getText().toString();
                String pwd = mEtPassword.getText().toString();
                mLoginPresenter.getUserData(userName,pwd);
            }
        });

    }

    @Override
    public void showLoading() {
        Log.d(TAG, "showLoading: ");
        mProgressDialog.show();
    }

    @Override
    public void hideLoading() {
        Log.d(TAG, "hideLoading: ");
        mProgressDialog.dismiss();
    }

    @Override
    public void showLoginSuccess(UserInfo userInfo) {
        Log.d(TAG, "showLoginSuccess: ");
        Toast.makeText(this,"登录成功",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showLoginFailed() {
        Log.d(TAG, "showLoginFailed: ");
        Toast.makeText(this,"登录失败",Toast.LENGTH_SHORT).show();
    }

    private static final String TAG = "MainActivity";


}

总结:
MVP框架模式完全将Model模型和View视图分离,从而使得代码的耦合低,利用MVP框架写项目达到解耦作用。 MVP和MVC最大的区别是:MVC中的V和C关系比较紧密,耦合度太高,从C中访问M获取数据一定程度上也可以看成从V中访问M。而MVP中M和V完全分离,互相不知道对方的存在,Presenter通过接口通信方式将V和M通信。 在Android中MVP框架 Activity担当View视图层,MVC框架模式Activity担当控制器。
Android架构设计之MVC模式

猜你喜欢

转载自blog.csdn.net/hzw2017/article/details/79633563