MVP架构的理解和使用

时间:2022-08-12 21:12:38

一、MVP:(Model-View-Presenter)

MVP架构的理解和使用

1、View:负责绘制UI元素、与用户进行交互(在Android中体现为Activity) 2、Model:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合) 3、Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。

二、MVP使用:

1、BaseView的接口:定义通用view接口

/**
* View的基类接口
* 定义一些通用的接口,例如显示加载页面,取消加载页面等
*/
public interface BaseView {
// void showLoading();
// void stopLoading();
}
2、BasePresenter基类:

关联view和model,(使用了RxJava,抽取添加入订阅队列和取消注册的相关方法)

public class BasePresenter<V,M> {

private CompositeSubscription mCompositeSubscription;
public V view;
public M model;

public BasePresenter(){

}

public BasePresenter(V view){
this.view = view;
model = createModel();
}

/**
* 创建model
* @return model对象
*/
public M createModel(){
return null;
}

//Rxjava取消注册,避免内存泄露
public void onUnsubscribe(){
if (mCompositeSubscription!=null&&mCompositeSubscription.hasSubscriptions()){
mCompositeSubscription.unsubscribe();
}
if (view!=null){
view=null;
}
}

//添加到订阅的队列
public void addSubscription(Observable observable, Subscriber subscriber){
if (mCompositeSubscription==null){
mCompositeSubscription = new CompositeSubscription();
}
mCompositeSubscription.add(observable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber));
}

}
3、BaseActivity:

通用的activity基类

public abstract class BaseActivity extends Activity{
public String TAG = null; //log
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getContentViewID() != 0) {
setContentView(getContentViewID());
}
//管理activity,将activity添加到集合中
BaseAppManager.getInstance().addActivity(this);
//注解
ButterKnife.bind(this);
TAG = this.getClass().getSimpleName();
//使用logUtils,统一管理是否显示log
LogUtils.init(TAG);
findView();
initView();
}

/**
* 初始化控件
*/
public void findView(){

}

/**
* 给控件赋值
*/
public void initView(){

}

/**
* bind layout resource file
* @return
*/
protected abstract int getContentViewID();

@Override
protected void onDestroy() {
super.onDestroy();
//将销毁的activity在集合中移除
BaseAppManager.getInstance().removeActivity(this);
}
}
4、MVP模式的基类Activity:

抽取了初始化Presenter和取消网络请求的方法

public abstract class BaseMVPActivity<P extends BasePresenter> extends BaseActivity{
public P presenter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
presenter = initPresenter();
}

/**
* 初始化Prensenter
*/
public abstract P initPresenter();

@Override
protected int getContentViewID() {
return 0;
}

/**
* 避免内存泄露,activity销毁,取消网络请求
*/
@Override
protected void onDestroy() {
super.onDestroy();
if (presenter!=null){
presenter.onUnsubscribe();
}
}
}
三、登录页面的例子:

1、LoginContract:

契约类,用来管理view、present、model相关接口

public interface LoginContract {

interface Presenter{
//登陆
void login(String mobile,String code);
//发送验证码
void sendVifycode(String moble);
}

interface View extends BaseView{
void showSendVifyToast(BaseEntity<String> baseEntity);
void loginSuccess(BaseEntity<UserEntity> userEntity);
}

//网络请求接口
interface Model {
//登录接口
@GET("user/vercodeLogin.go")
Observable<BaseEntity<UserEntity>> login(@Query("mobileNo") String phone,@Query("vercode") String code,@Query("appType") int type);
//发送验证码的接口
@GET("user/sendVerCode.go")
Observable<BaseEntity<String>> sendVifyCode(@Query("mobileNo") String phone);
}
}
2、LoginActivity:

实现view接口,用来和presenter进行交互

public class LoginActivity extends BaseMVPActivity<LoginPresenter> implements LoginContract.View, View.OnClickListener {
private EditText mobileText; //手机号
private EditText vercodeText;//验证码
private Button submitBtm; //发送验证码按钮
private Button loginBtm;//登录按钮

@Override
protected int getContentViewID() {
return R.layout.activity_login;
}

@Override
public void findView() {
super.findView();
mobileText = (EditText) findViewById(R.id.id_login_mobilno_value);
vercodeText = (EditText) findViewById(R.id.id_login_vercode_value);
submitBtm = (Button) findViewById(R.id.id_login_vercode_btn);
loginBtm = (Button) findViewById(R.id.id_login_btn);
submitBtm.setOnClickListener(this);
loginBtm.setOnClickListener(this);
}

@Override
public LoginPresenter initPresenter() {
return new LoginPresenter(this);
}

//发送验证码后的页面处理
@Override
public void showSendVifyToast(BaseEntity<String> baseEntity) {

}

//登录成功
@Override
public void loginSuccess(BaseEntity<UserEntity> userEntity) {
startActivity(new Intent(this,MyActivity.class));
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.id_login_vercode_btn:
presenter.sendVifycode(mobileText.getText().toString());
break;
case R.id.id_login_btn:
presenter.login(mobileText.getText().toString(),vercodeText.getText().toString());
break;
default:
break;
}
}
}
3、LoginPresenter:

用来关联view层和model层

public class LoginPresenter extends BasePresenter<LoginActivity,LoginModel> implements LoginContract.Presenter{

public LoginPresenter(LoginActivity view) {
super(view);
}

@Override
public LoginModel createModel() {
return new LoginModel();
}

@Override
public void login(String mobile, String code) {
addSubscription(model.login(mobile,code,0),new SubscriberCallBack(new ApiCallBack<BaseEntity<UserEntity>>() {
@Override
public void onSuccess(BaseEntity<UserEntity> model) {
//登录成功
view.loginSuccess(model);
}

@Override
public void onFailure() {

}

@Override
public void onCompleted() {

}
}));

}
@Override
public void sendVifycode(String moble) {
addSubscription(model.sendVifyCode(moble),new Subscriber<BaseEntity<String>>() {
@Override
public void onCompleted() {

}

@Override
public void onError(Throwable e) {

}

@Override
public void onNext(BaseEntity<String> baseEntity) {
view.showSendVifyToast(baseEntity);
}
});

}
}
4、LoginModel

进行和presenter交互,处理网络请求

public class LoginModel extends BaseModel implements LoginContract.Model {
LoginContract.Model service = BaseHttpMethod.getInstance().create(LoginContract.Model.class);

@Override
public Observable<BaseEntity<UserEntity>> login(String phone,String code,int type) {
return service.login(phone,code,type);
}

@Override
public Observable<BaseEntity<String>> sendVifyCode(String phone) {
return service.sendVifyCode(phone);
}
}

总结:mvp的变异使用

1、model层主要是bean,presenter进行网络请求
2、去掉Contract契约类,不进行相关接口管理。有的甚至去掉接口,直接定义方法进行view和presenter的交互。

3、结合mvvm,使用viewmodel,进行view和model的数据绑定,从model获取必要数据,提供给view进行展示。