Android MVP模式初次实践

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

  
  
Android MVP模式初次实践
从上图可知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模式的实例

Android 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模式使用的新手,一些接口使用起来确实有绕,但是写完后对代码多思考几遍,还是可以顺利理解的。

作者:争风24