關(guān)于mvp框架的使用赡矢,已經(jīng)有很多文章記介紹了杭朱。MVP的概念就不再闡述,本文純屬記錄下自己的使用心得吹散,方便后續(xù)自己查看弧械。
如上圖所示,有四個關(guān)鍵字空民,分別是:Contract刃唐、IBaseView羞迷、IBaseModel、BasePresenter画饥。
正如圖中所介紹的衔瓮,Contract是M、V抖甘、P的契約热鞍。Contract是Interface,每一組mvp行為對應(yīng)一個Contract衔彻。每一個Contract 包含3個interface薇宠,分別是M、V艰额、P澄港。結(jié)合??代碼方便理解Contract。
(登錄案例)
public interface LoginContract {
interface Model extends IBaseModel {
/**
* 統(tǒng)一登錄接口
* @param userName 用戶名
* @param password 密碼
* @param authType 認(rèn)證類型:1-默認(rèn) 4-手勢密碼
* @param callback 回調(diào)
*/
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);
}
}
梳理流程:
點(diǎn)擊登錄按鈕柄沮,調(diào)用LoginContract.Presenter#login
方法。在login方法的實(shí)現(xiàn)中漂辐,調(diào)用LoginContract.Model#login
棕硫,并通過回調(diào)的方式(ResponseCallback)返回結(jié)果髓涯,并在回調(diào)函數(shù)中執(zhí)行視圖操作LoginContract.View#loginSuccess
哈扮。
??ResponseCallback
public interface ResponseCallback<T> {
void success(T response);
void fail(String s);
void error(String error);
}
Contract中的M和P需要自定義對應(yīng)的類,V需要在對應(yīng)的Activity implements滑肉。
??Model:implements LoginContract.Model包各,重寫login方法问畅,并回調(diào)返回結(jié)果护姆。
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("網(wǎng)絡(luò)通信異常掏击,請重試");
}
}
@Override
public void onFailure(Call<LoginBean> call, Throwable t) {
t.printStackTrace();
callback.fail(t.getMessage());
}
});
}
}
??Presenter:繼承BasePresenter灯变,implements LoginContract.Presenter。重寫login滚粟、createModule方法坦刀。login方法中調(diào)用Model的login,并在定義的回調(diào)函數(shù)中林艘,調(diào)用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("用戶未開通登錄權(quán)限");
} 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();
}
??????//點(diǎn)擊登錄事件
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);
}
/**
* 通過該方法創(chuàng)建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;
}
}