一,概述
如上图看起来很好理解,其中View中包含了Presenter,Presenter中有View的接口和Model,可以调用View和Model。Model可以说完全独立。MVP与MVC的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter 来进行的,所有的业务逻辑都在Presenter,而在MVC中View会直接从Model中读取数据而不是通过 Controller。
MVP优点:
1、对MVC进一步解耦,model与view完全分离
2、单元测试,因逻辑都在Presenter,presenter的逻辑就可以方便单元测试,还有Model也很好测试
3、重用性,我们可以把Presenter用于不同的view上,还有Model更加可以独立使用
二,示例
下面模式是参考google的todoapp mvp示例
1,接口封装
package com.jerrycai.mymvp.login;
import com.jerrycai.mymvp.base.IView;
import com.jerrycai.mymvp.bean.User;
/**
* Created by JerryCai on 2017/1/18.
*/
public interface LoginContract {
interface View extends IView {
void loginSuccess(User user);
void loginFailure(String code, String msg);
}
interface Presenter {
void login(String phone, String pwd);
}
}
2,Model
package com.jerrycai.mymvp.service;
import com.jerrycai.mymvp.callback.Callback;
/**
* Created by JerryCai on 2017/1/18.
*/
public class UserService {
public void login(String phone, String pwd, Callback callback) {
//连网处理
}
}
3,View
package com.jerrycai.mymvp.login;
import android.app.Activity;
import android.os.Bundle;
import com.jerrycai.mymvp.bean.User;
/**
* Created by JerryCai on 2017/1/18.
*/
public class LoginActivity extends Activity implements LoginContract.View {
private LoginContract.Presenter mPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPresenter = new LoginPresenter(this);
mPresenter.login("test","test");
}
@Override
public void loginSuccess(User user) {
//成功处理
}
@Override
public void loginFailure(String code, String msg) {
//失败处理
}
}
4,Presenter
package com.jerrycai.mymvp.login;
import com.jerrycai.mymvp.base.BasePresenter;
import com.jerrycai.mymvp.bean.User;
import com.jerrycai.mymvp.callback.Callback;
import com.jerrycai.mymvp.service.UserService;
/**
* Created by JerryCai on 2017/1/18.
*/
public class LoginPresenter extends BasePresenter<UserService, LoginContract.View> implements LoginContract.Presenter {
public LoginPresenter(LoginContract.View view) {
super(new UserService(), view);
}
@Override
public void login(String phone, String pwd) {
mMoudel.login(phone, pwd, new Callback<User>() {
@Override
public void onSuccess(User user) {
mView.loginSuccess(user);
}
@Override
public void Failure(String code, String msg) {
mView.loginFailure(code, msg);
}
});
}
}
三,一些思考
现在要加多一个功能,手机登录当然要获取验证码,而找回密码也要获取手机验证码,一般会写成同一个接口不同参数,这样我们的Model,View和Presenter怎么处理呢。
我看过不少人会Presenter是和界面挂钩,其中包括我以前也这样。若他们分工是A做登录,B做找回密码,他们可能会弄了一个LoginPresenter(有获取验证码的处理和有登录的处理)和一个ForgotPwdPresenter(有获取验证码的处理和有提交找回密码的处理),相应的View实现的功能也会实现一套一样的,Model估计倒不会再加一个。这样重用性明显少了点,model可以重用,presenter却不能重用了。那我们的Presenter不能和界面挂钩应该和model挂钩才对,一个界面应该允许多个不同功能逻辑的presenter,View可以实现多个View接口。下面上代码:
1,VerificationCodeContract
package com.jerrycai.mymvp.contract;
import com.jerrycai.mymvp.base.IView;
/**
* Created by JerryCai on 2017/1/18.
*/
public interface VerificationCodeContract {
interface View extends IView {
void onCodeCallback(boolean success, String errorMsg);
}
interface Presenter {
void getCode(String phone, int type);
}
}
2,VerificationCodeService
package com.jerrycai.mymvp.service;
import com.jerrycai.mymvp.callback.Callback;
/**
* Created by JerryCai on 2017/1/18.
*/
public class VerificationCodeService {
public void getCode(String phone, int type, Callback callback) {
//连网处理
}
}
3,VerificationCodePresenter
package com.jerrycai.mymvp.presenter;
import com.jerrycai.mymvp.base.BasePresenter;
import com.jerrycai.mymvp.callback.Callback;
import com.jerrycai.mymvp.contract.VerificationCodeContract;
import com.jerrycai.mymvp.service.VerificationCodeService;
/**
* Created by JerryCai on 2017/1/18.
*/
public class VerificationCodePresenter extends BasePresenter<VerificationCodeService, VerificationCodeContract.View> implements VerificationCodeContract.Presenter {
public VerificationCodePresenter(VerificationCodeContract.View view) {
super(new VerificationCodeService(), view);
}
@Override
public void getCode(String phone, int type) {
mMoudel.getCode(phone, type, new Callback() {
@Override
public void onSuccess(Object o) {
mView.onCodeCallback(true, null);
}
@Override
public void Failure(String code, String msg) {
mView.onCodeCallback(false, msg);
}
});
}
}
4,LoginActivity
package com.jerrycai.mymvp.login;
import android.app.Activity;
import android.os.Bundle;
import com.jerrycai.mymvp.bean.User;
import com.jerrycai.mymvp.contract.LoginContract;
import com.jerrycai.mymvp.contract.VerificationCodeContract;
import com.jerrycai.mymvp.presenter.LoginPresenter;
import com.jerrycai.mymvp.presenter.VerificationCodePresenter;
/**
* Created by JerryCai on 2017/1/18.
*/
public class LoginActivity extends Activity implements LoginContract.View,VerificationCodeContract.View {
private LoginContract.Presenter mPresenter;
private VerificationCodeContract.Presenter mCodePresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//-------------示范用的,直接写在这样而已
mPresenter = new LoginPresenter(this);
mPresenter.login("test","test");
mCodePresenter = new VerificationCodePresenter(this);
mCodePresenter.getCode("test",0);
}
@Override
public void loginSuccess(User user) {
//成功处理
}
@Override
public void loginFailure(String code, String msg) {
//失败处理
}
@Override
public void onCodeCallback(boolean success, String errorMsg) {
//处理验证码
}
}
这样LoginPresenter和VerificationCodePresenter都可以重用,用在不同的东西,还有service肯定也可以的,也便于单元测试