做过java前端开发的开发人员对mvc设计模式都不陌生,MVP是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter(MVC中的Controller)来进行的,所有的交互都发生在Presenter内部。
在MVP模式里通常包含4个要素:
- View:负责绘制UI元素、与用户进行交互(在Android中体现为Activity);
- View interface:需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试;
- Model:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合);
- Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。
在Android开发中,Activity的首要职责是加载应用的布局和初始化用户界面,并接受并处理来自用户的操作请求,进而作出响应。随着界面及其逻辑的复杂度不断提升,Activity类的 职责不断增加,以致变得庞大臃肿。当我们将其中复杂的逻辑处理移至另外的一个类(Presneter)中时,Activity其实就是MVP模式中View,它负责UI元素的初始化,建立UI元素与Presenter的关联(Listener之类),同时自己也会处理一些简单的逻辑(复杂的逻辑交由 Presenter处理).
另外,回想一下你在开发Android应用时是如何对代码逻辑进行单元测试的?是否每次都要将应用部署到Android模拟器或真机上,然后通过模拟用 户操作进行测试?然而由于Android平台的特性,每次部署都耗费了大量的时间,这直接导致开发效率的降低。而在MVP模式中,处理复杂逻辑的 Presenter是通过interface与View(Activity)进行交互的,这说明了什么?说明我们可以通过自定义类实现这个 interface来模拟Activity的行为对Presenter进行单元测试,省去了大量的部署及测试的时间。
MVP模式的m(模型)层:
封装一些数据,具有我们实际业务逻辑的要实现的方法
<span style="font-size:14px;">package com.ayit.mvpmodel.model; import com.ayit.mvpmodel.listener.IStatusCallback; /** * Created by Sweetheart on 2015/11/2 19:29. * Email: 378398018@qq.com * <br/> * MVP模式的m(模型)层。 * 登陆状态,登陆的实际逻辑实现它去完成。 */ public interface ILoginStatus extends IStatus { public static final int STATUS_VERIFY_FAIL = -1;//验证失败 public static final int STATUS_LOGIN_FAIL = -2;//登陆失败 public static final int STATUS_LOGIN_SUCCESS = 0;//登陆成功 public static final int STATUS_LOGIN_ING = 1;//登陆中 /** * 登陆 * @param account * @param psw * @return 状态码 */ public void login(String account,String psw,IStatusCallback callback); }</span><span style="font-size: 24px;"> </span>
package com.ayit.mvpmodel.model.impl;
import android.os.AsyncTask;
import android.text.TextUtils;
import com.ayit.mvpmodel.listener.IStatusCallback;
import com.ayit.mvpmodel.model.ILoginStatus;
/**
* Created by Sweetheart on 2015/11/2 19:32.
* Email: 378398018@qq.com
* <br/>
* 实现类,处理数据
*/
public class LoginStatus implements ILoginStatus {
private int status = ILoginStatus.STATUS_LOGIN_ING;
private String msg = "";
@Override
public void login(final String account, final String psw,
final IStatusCallback callback) {
new AsyncTask<String, Void, ILoginStatus>() {
@Override
protected ILoginStatus doInBackground(String... arg0) {
if (varify(account, psw)) {
try {//模拟网络请求耗时处理
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if ("mvpmodel".equals(account) && "mvp".equals(psw)) {
status = ILoginStatus.STATUS_LOGIN_SUCCESS;
msg = "Success";
} else {
status = ILoginStatus.STATUS_LOGIN_FAIL;
msg = "Failed";
}
}
return LoginStatus.this;
}
@Override
protected void onPreExecute() {
callback.onStatus(LoginStatus.this);
}
@Override
protected void onPostExecute(ILoginStatus result) {
callback.onStatus(result);
}
}.execute();
}
/**
* 本地校验
* @param account
* @param psw
* @return
*/
private boolean varify(String account, String psw) {
if (TextUtils.isEmpty(account)) {
status = ILoginStatus.STATUS_VERIFY_FAIL;
msg = "Username cannot be empty";
return false;
}
if (TextUtils.isEmpty(psw)) {
status = ILoginStatus.STATUS_VERIFY_FAIL;
msg = "Password cannot be empty";
return false;
}
return true;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
MVP模式的V(视图)层
* 这是一个抽象的登陆视图,里面都是一些界面动作,想要执行这些动作的界面都会去实现它。
package com.ayit.mvpmodel.view; /** * Created by Sweetheart on 2015/11/2 19:36. * Email: 378398018@qq.com * <br/> * MVP模式的V(视图)层 * 这是一个抽象的登陆视图,里面都是一些界面动作,想要执行这些动作的界面都会去实现它。 */ public interface ILoginView extends IView { /** * 弹出提示信息。 */ public void showMsg(String msg); /** * 成功登陆跳转主页。 */ public void moveToMain(); /** * 加载中 */ public void showLoadding(); /** * 隐藏 */ public void hideLoadding(); }
package com.ayit.mvpmodel;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.ayit.mvpmodel.presenter.LoginPersenter;
import com.ayit.mvpmodel.view.ILoginView;
public class MainActivity extends AppCompatActivity implements ILoginView,
View.OnClickListener {
private ProgressDialog dialog;
private EditText etAccount, etPsw;
private Button btnLogin;
private LoginPersenter mPersenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPersenter = new LoginPersenter(this);
initViews();
}
@Override
public void showMsg(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
@Override
public void moveToMain() {
Intent toMain = new Intent(this, MainActivity.class);
startActivity(toMain);
}
@Override
public void showLoadding() {
dialog.show();
}
@Override
public void hideLoadding() {
dialog.cancel();
}
public void initViews() {
dialog = new ProgressDialog(this);
dialog.setMessage("加载中。。。");
etAccount = (EditText) findViewById(R.id.et_account);
etPsw = (EditText) findViewById(R.id.et_psw);
btnLogin = (Button) findViewById(R.id.btn_login);
btnLogin.setOnClickListener(this);
}
@Override
public void onClick(View arg0) {
switch (arg0.getId()) {
case R.id.btn_login:
mPersenter.didLoginSuccess(etAccount.getText().toString(), etPsw
.getText().toString());
break;
default:
break;
}
}
}
最后,就是MVP模式中的Persenter了,它负责主导所有的模型和视图
package com.ayit.mvpmodel.presenter;
import com.ayit.mvpmodel.listener.IStatusCallback;
import com.ayit.mvpmodel.model.ILoginStatus;
import com.ayit.mvpmodel.model.IStatus;
import com.ayit.mvpmodel.model.impl.LoginStatus;
import com.ayit.mvpmodel.view.ILoginView;
/**
* Created by Sweetheart on 2015/11/2 19:41.
* Email: 378398018@qq.com
* <br/>
* MVP模式中的P(主导器),它负责主导所有的模型和视图。
*/
public class LoginPersenter {
private ILoginView mLoginView;// 持有视图对象
private ILoginStatus mStatus;// 持有模型
public LoginPersenter(ILoginView mLoginView) {
mStatus = new LoginStatus();
this.mLoginView=mLoginView;
}
public void didLoginSuccess(String account, String psw) {
mStatus.login(account, psw, new IStatusCallback() {
@Override
public void onStatus(IStatus status) {
LoginStatus s = (LoginStatus) status;
switch (s.getStatus()) {
case ILoginStatus.STATUS_VERIFY_FAIL:// 验证失败
case ILoginStatus.STATUS_LOGIN_FAIL:// 登陆失败
mLoginView.hideLoadding();
mLoginView.showMsg(s.getMsg());
break;
case ILoginStatus.STATUS_LOGIN_ING:// 登陆中
mLoginView.showLoadding();
break;
case ILoginStatus.STATUS_LOGIN_SUCCESS:// 登陆成功
mLoginView.hideLoadding();
mLoginView.moveToMain();
break;
default:
break;
}
}
});
}
}
以上,我也是看网上别人的介绍及自己总结出来的,希望对你们有帮助。