关于mvp框架的使用,已经有很多文章记介绍了。MVP的概念就不再阐述,本文纯属记录下自己的使用心得,方便后续自己查看。
如上图所示,有四个关键字,分别是:Contract、IBaseView、IBaseModel、BasePresenter。
正如图中所介绍的,Contract是M、V、P的契约。Contract是Interface,每一组mvp行为对应一个Contract。每一个Contract 包含3个interface,分别是M、V、P。结合👇代码方便理解Contract。
(登录案例)
public interface LoginContract {
interface Model extends IBaseModel {
/**
* 统一登录接口
* @param userName 用户名
* @param password 密码
* @param authType 认证类型:1-默认 4-手势密码
* @param callback 回调
*/
void login(String userName, String password,String authType,ResponseCallback<LoginBean> callback);
}
interface View extends IBaseView {
void loginSuccess(String token);
}
interface Presenter {
void login(String userName,String password,String authType);
}
}
梳理流程:
点击登录按钮,调用LoginContract.Presenter#login
方法。在login方法的实现中,调用LoginContract.Model#login
,并通过回调的方式(ResponseCallback)返回结果,并在回调函数中执行视图操作LoginContract.View#loginSuccess
。
👇ResponseCallback
public interface ResponseCallback<T> {
void success(T response);
void fail(String s);
void error(String error);
}
Contract中的M和P需要自定义对应的类,V需要在对应的Activity implements。
👇Model:implements LoginContract.Model,重写login方法,并回调返回结果。
public class LoginModel implements LoginContract.Model {
@Override
public void login(String userName, String password, String authType,ResponseCallback<LoginBean> callback) {
...
PlatformService service = RetrofitClientMptl.getService(PlatformService.class);
Call<LoginBean> call = service.lockLogin(body);
Cutscenes.show(null,null,false,false);
call.enqueue(new Callback<LoginBean>() {
@Override
public void onResponse(Call<LoginBean> call, Response<LoginBean> response) {
if (response.isSuccessful()){
callback.success(response.body());
} else {
//TODO
callback.error("网络通信异常,请重试");
}
}
@Override
public void onFailure(Call<LoginBean> call, Throwable t) {
t.printStackTrace();
callback.fail(t.getMessage());
}
});
}
}
👇Presenter:继承BasePresenter,implements LoginContract.Presenter。重写login、createModule方法。login方法中调用Model的login,并在定义的回调函数中,调用View的loginSuccess方法。
public class LoginPresenter extends BasePresenter<LoginContract.Model,LoginContract.View>
implements LoginContract.Presenter {
@Override
public void login(String userName,String password,String authType) {
if(isViewAttached()){
getView().showLoading();
getModule().login(userName, password, authType, new ResponseCallback<LoginBean>() {
@Override
public void success(LoginBean response) {
getView().dismissLoading();
if(response.getError() == null){
getView().loginSuccess(response.getAccess_token());
} else if(response.getError().equals("invalid_grant")){
toast("用户名或密码错误");
} else if(response.getError().equals("unauthorized")){
toast("用户未开通登录权限");
} else {
toast("登录失败");
}
}
@Override
public void fail(String s) {
toast(s);
getView().dismissLoading();
}
@Override
public void error(String error) {
toast(error);
getView().dismissLoading();
}
});
}
}
@Override
protected LoginContract.Model createModule() {
return new LoginModel();
}
@Override
public void start() {
}
}
👇剩下的View呢
public class LoginActivity extends BaseMVPActivity<LoginPresenter>
implements LoginContract.View {
@Override
protected void initPresenter() {
mPresenter = new LoginPresenter();
}
👇👇👇//点击登录事件
public void login(View view) {
mPresenter.login(userName, password, "1");
}
👇👇👇
@Override
public void loginSuccess(String token) {
startActivity(new Intent(LoginActivity.this, HomeActivity.class));
finish();
}
}
👇MVP的基类和BaseMVPActivity基类:👇
IBaseModel
public interface IBaseModel {
}
IBaseView
public interface IBaseView {
/**
* 显示加载框
*/
void showLoading();
/**
* 隐藏加载框
*/
void dismissLoading();
void toast(String msg);
/**
* 上下文
*
* @return context
*/
Context getContext();
}
BasePresenter
public abstract class BasePresenter<M extends IBaseModel, V extends IBaseView> {
private WeakReference<V> mvpView;
private M mvpModel;
/**
* 绑定View
*/
@SuppressWarnings("unchecked")
public void attachView(V view) {
mvpView = new WeakReference<>(view);
if (mvpModel == null) {
mvpModel = createModule();
}
}
/**
* 解绑View
*/
public void detachView() {
if (null != mvpView) {
mvpView.clear();
mvpView = null;
}
this.mvpModel = null;
}
/**
* 是否与View建立连接
*/
protected boolean isViewAttached() {
return null != mvpView && null != mvpView.get();
}
protected V getView() {
return isViewAttached() ? mvpView.get() : null;
}
protected M getModule() {
return mvpModel;
}
protected Context getContext() {
return getView().getContext();
}
protected void showLoading() {
getView().showLoading();
}
protected void dismissLoading() {
getView().dismissLoading();
}
protected void toast(String s) {
getView().toast(s);
}
/**
* 通过该方法创建Module
*/
protected abstract M createModule();
/**
* 初始化方法
*/
public abstract void start();
}
BaseMVPActivity
public abstract class BaseMVPActivity<P extends BasePresenter> extends AppCompatActivity implements IBaseView {
protected P mPresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(initLayout());
ActivityUtil.push(this);
//初始化mPresenter
initPresenter();
//绑定view
if(mPresenter != null){
mPresenter.attachView(this);
}
//初始化
initView();
initData();
}
protected abstract void initData();
/**
* 初始化mPresenter
*/
protected abstract void initPresenter();
/**
* 初始化
*/
protected abstract void initView();
/**
* 获取布局id
* @return
*/
protected abstract int initLayout();
@Override
protected void onDestroy() {
super.onDestroy();
if(mPresenter != null){
mPresenter.detachView();
mPresenter = null;
}
ActivityUtil.remove(this);
}
@Override
public void toast(String msg) {
Toast.makeText(this,msg,Toast.LENGTH_SHORT).show();
}
@Override
public void showLoading() {
Cutscenes.show(null,null,false,false);
}
@Override
public void dismissLoading() {
Cutscenes.dismiss(true);
}
@Override
public Context getContext() {
return this;
}
}