一、什么是MVP?
MVP是基于MVC提出来的,MVC模式在android开发中的体现不是特别的明显,尤其是当我们按照传统的写法,会在Activity和Fragment中写大量的业务逻辑和UI界面操作的代码,以至于Controller和View分隔的不是特别的明显。然而MVP的出现完美的解决了Activity/Fragment中业务逻辑和界面操作的耦合问题。简而言之,MVP的出现就是为了解耦,提高代码可维护性。
MVP中:Presenter在这里充当了MVC中Controller的角色,Model只能通过Presenter来通知View进行界面的更新。代码结构如下图所示:
Data Layer:非传统意义的 Model 层,包含 dto(Data Transfer Object)、service 和 model。其中 service 包含 Net和 Local 等不同服务,用于提供不同的数据服务。model 负责处理某个业务对象的业务逻辑,并通过 dto 或元数据 与 Presenter 层进行交互。
View Layer:视图层,包括各种activity,adapter,fragment,view。只关注与用户交互,以及视图操作(动画、界面输出、更新等)。
Presenter Layer:控制逻辑层。将控制逻辑从 Activity 中剥离并抽象成不同的Presenter。负责「View 与 Model 层之间的控制与交互」。
废话不多说了,下面上一个简单的例子,体验一下MVP设计模式:
这里模拟一下用户登录的场景,输入账号和密码,后台请求验证账号密码是否正确,正确的话就直接登录成功。
首先看一下代码的层级结构:
这里我么的bean下面的就相当于我们model层下面封装好的数据实体,biz下面就是我们的登陆的业务逻辑,presenter下面负责View和Model之间的交互。
User实体类的代码:就两个参数,一个登陆账号,一个登陆密码
package com.guannan.mvpdemo.bean;
/**
* Created by guannan on 2016/10/11.
*/
public class User {
private String account;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
}
biz(业务逻辑层的代码),这里我们有一个登陆的需求所以我们提供一个登陆的接口IUserLogin,下面有一个login方法,假如我们有其他登陆相关的方法可以在这里面进行添加
package com.guannan.mvpdemo.biz;
/**
* Created by guannan on 2016/10/11.
*/
public interface IUserLogin {
public void login(String username,String password,OnLoginListener loginListener);
}
然后我们的OnLoginListener下面使我们登陆成功以后所回调的方法,这个接口作为我们和Presenter层的交互
package com.guannan.mvpdemo.biz;
import com.guannan.mvpdemo.bean.User;
/**
* Created by guannan on 2016/10/11.
*/
public interface OnLoginListener {
void loginSuccess(User user); //登录成功
void loginFaild(); //登录失败
}
最后的UserLogin实现IUserLogin完成我们整个登录的业务逻辑
package com.guannan.mvpdemo.biz;
import com.guannan.mvpdemo.bean.User;
/**
* Created by guannan on 2016/10/11.
*/
public class UserLogin implements IUserLogin {
@Override
public void login(final String username, final String password, final OnLoginListener loginListener) {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if("zgn".equals(username) && "123".equals(password)){
User user=new User();
user.setAccount(username);
user.setPassword(password);
loginListener.loginSuccess(user); //登录成功
}else{
loginListener.loginFaild(); //登录失败
}
}
}).start();
}
}
这里重点看一个LoginPresenter所完成的操作,这里调用了UserLogin里面的login方法,并通过OnLoginListener的接口回调进行登录成功和失败的操作。
package com.guannan.mvpdemo.presenter;
import android.content.Intent;
import android.os.Handler;
import com.guannan.mvpdemo.SuccessActivity;
import com.guannan.mvpdemo.bean.User;
import com.guannan.mvpdemo.biz.IUserLogin;
import com.guannan.mvpdemo.biz.OnLoginListener;
import com.guannan.mvpdemo.biz.UserLogin;
import com.guannan.mvpdemo.view.ILoginView;
/**
* Created by guannan on 2016/10/11.
*/
public class LoginPresenter {
IUserLogin mIUserLogin;
ILoginView mILoginView;
private Handler mHandler=new Handler();
public LoginPresenter(ILoginView iLoginView){
this.mIUserLogin=new UserLogin();
this.mILoginView=iLoginView;
}
public void login(){
mIUserLogin.login(mILoginView.getUserName(), mILoginView.getPassword(), new OnLoginListener() {
@Override
public void loginSuccess(User user) {
mHandler.post(new Runnable() {
@Override
public void run() {
mILoginView.clearPassword();
mILoginView.clearUsername();
Intent intent=new Intent(mILoginView.getActivity(), SuccessActivity.class);
mILoginView.getActivity().startActivity(intent);
mILoginView.getActivity().finish();
}
});
}
@Override
public void loginFaild() {
}
});
}
}
另外我们登录成功或者失败后需要对View层的Activity的界面进行一些操作,这里提供了另外一个接口ILoginView,这里主要是LoginPresenter层对UI层的一些界面操作(获取账号getUsername(),获取密码getPassword(),清空账号clearUsername(),清空密码clearPassword())。
package com.guannan.mvpdemo.view;
import android.app.Activity;
/**
* Created by guannan on 2016/10/11.
*/
public interface ILoginView {
public String getUserName();
public String getPassword();
public void clearUsername();
public void clearPassword();
public Activity getActivity();
}
Presenter层和View层的交互就是通过接口回调的方式,Model层和Presenter层的交互可以通过接口回调的方式,当然也可以采用EventBus,otto等方式。这里不再介绍。
好久没写博客了,就写到这里,大神请飘过,欢迎吐槽~
参考资料:
https://zhuanlan.zhihu.com/p/20358928
https://www.zhihu.com/question/35185744
http://blog.csdn.net/lmj623565791/article/details/46596109
http://rocko.xyz/2015/02/06/Android%E4%B8%AD%E7%9A%84MVP/