您的位置:首页 > 移动开发 > Android开发

MVP模式在项目中的使用

2016-06-24 15:45 405 查看
1.MVP模式的简介:

相对于mvc,mvp模式中p就是presenter的缩写,意思相当于主持人,它协调view和model的连接,view和model相当于是两个不认识的人,他们中间的中介就是presenter,p持有m和v两个的联系方式。view要处理页面就要要数据,就去找p,让p去拿数据。而p呢就会直接找m去要数据,m把数据给p,然后p拿着数据进行加工,然后给v有用的数据,来用于v的展示。这个过程很像我们通过中介找房子。中介有我们和出租房的联系方式,可以通过查询系统,获取到出租房的房源信息,然后给我们最后有用的信息,比如房屋价格,环境等。但是我们是和房东没有办法直接联系的。这就是mvp。而mvc的话v是可以持有model数据的,这就导致v可能会对model做数据修改。导致会掺杂一些业务逻辑。使得业务逻辑在m和c以及v中混杂到一起。这个典型的例子就是activity。既要控制显示,还要管理数据。非常混乱。而为了更好的分层,还有后续如果我换v和m都没有很大影响的话,我们就延伸出了mvp。就如那个中介,它可以换一套查询系统和房东信息,也可以换租户,但是实现的模式还是不变的。






2.MVP模式具体使用方法:

在项目中的使用:

我们通常需要以接口的形式来实现三者的关系,这样方便后续的扩展。

以登陆为例:

Model:

/**
* 描述:登录界面请求接口
 *
*/
public interface LoginInteractor extends MvpInteractor {
/*** 登录
* @param phone
* @param pwd
* @param loginInteractorListener
*/
void userLogin(String phone, String pwd, LoginInteractorListener loginInteractorListener);
/*** 请求接口监听器
*/
interface LoginInteractorListener {
/*** 请求成功且业务代码 也成功
*/
void succeed();

/*** 请求成功,但是业务代码失败
* @param message
*/
void failed(String message);

/*** 请求失败
*
* @param error
*/
void connectFail(String error);
}
}


View:

/*** 描述:
* 作者:58 on 2016/5/11 10:41
*/
public interface LoginView extends MvpView {
/*** 登录成功view显示
*/
void loginSucceed();

/*** 登录失败view显示
* @param message
*/
void loginFailed(String message);

void showNotice(String message);

void showNotice(String message);
/**     
* 返回当前登录界面btn的状态 
* @param canClick  
*/  
void isCanClick(boolean canClick);
void loadingDismiss();
}


Presenter:

/**
 * 描述:登录界面逻辑控制器
*/
public interface LoginPresenter extends MvpPresenter<LoginView> {
/*** 登录
* @param phone
* @param pwd
*/
void login(String phone, String pwd, String validcode);
/*** 检测是否可以点击登录btn
* @param userPhone
* @param password
*/
void checkClickBtn(String userPhone, String password);
}


public interface MvpPresenter<T extends MvpView> {

/*** 将MVP的View附加到Presenter
*/
void attachView(T view);
void attachView(T view,ViewGroup rootView);
void detachView();
}


具体的实现类如下:

/**
* 描述:登录界面逻辑控制器实现
*/
public class LoginPresenterImpl implements LoginPresenter, LoginInteractor.LoginInteractorListener, GetPictureVerCodeInteractor.GetPictureVerCodeInteractorListener {
private LoginView mLoginView;
private Context mContext;
private LoginInteractor mLoginInteractor;
public LoginPresenterImpl(Context context) {
mContext = context;
mAccount = Account.getAccount(mContext);
}
@Override
public void attachView(LoginView view) {
mLoginView = view;
mLoginInteractor = new LoginInteractorImpl(mContext);
}
@Override
public void attachView(LoginView view, ViewGroup rootView) {
}
@Override
public void detachView() {
mLoginInteractor.cancelAllRequest();
mContext = null;
mLoginView = null;
}
@Override
public void login(String phone, String pwd, String validcode) {
mLoginInteractor.userLogin(phone, pwd, this);
}
@Override
public void checkClickBtn(String userPhone, String password) {
boolean canClick = !userPhone.isEmpty() && userPhone.length() == 11 && !password.isEmpty() && password.length() >= 6;
mLoginView.isCanClick(canClick);
}
@Override
public void succeed() {
mLoginInteractor.sendPPU(this);
}
@Override
public void failed(String message) {
mLoginView.loginFailed(message);
}
@Override
public void connectFail(String error) {
mLoginView.showNotice(error);
}
@Override
public void requestFinish() {
mLoginView.loadingDismiss();
}
}

Model:

/**
* 描述:登录界面请求接口实现类
*/
public class LoginInteractorImpl implements LoginInteractor {
public Context mContext;

public LoginInteractorImpl(Context context) {
mContext = context;
}
@Override
public void cancelRequest(String requestTag) {
HttpManager.getHttpManagerBase(mContext).cancelRequest(requestTag);
}
@Override
public void cancelAllRequest() {
HttpManager.getHttpManagerBase(mContext).cancelRequest(ConstantConfig.LOGIN_TAG);
mContext = null;
}
@Override
public void userLogin(final String phone, final String pwd, final String validcode, final String vcodekey, final LoginInteractorListener loginInteractorListener) {
final Map<String, String> map = setParams(phone, pwd, validcode, vcodekey);
LogUtil.i("userlogin", map.toString());
String url = "http://test/login;   //这里只做示例
HttpManager.getHttpManagerBase(mContext).httpPost(url, map, ConstantConfig.LOGIN_TAG, new RequestResultListener() {
@Override
public void onSuccess(String info, Object tag) {
Log.e("--------------", info);
Gson gson = new Gson();
LoginInfo loginInfo = gson.fromJson(info, LoginInfo.class);
if (loginInfo != null) {
loginInteractorListener.succeed();
}
loginInteractorListener.requestFinish();

}
@Override
public void onFail(String code, String msg, String info, Object tag) {

loginInteractorListener.failed(msg);

loginInteractorListener.requestFinish();
}
@Override
public void connectFail(NetworkResponse error, Object tag) {
LogUtil.i("wuba", "connectFail");
loginInteractorListener.connectFail("网络异常请重试");
loginInteractorListener.requestFinish();
}
});
}
}


我们可以让我们的Activity实现View的接口即可。如下

public class LoginActivity extends BaseActivity implements LoginView {
。。。。。此处隐去1000字
public void loginSucceed() {
ToastUtil.show(this, "登录成功");
if (mDialog != null) {
dialogIsShow = false;
mDialog.dismiss();
}
loginIntent();

}
@Override
public void loginFailed(String message) {
if (mDialog != null) {
mDialog.dismiss();
dialogIsShow = false;
}
if (TextUtils.isEmpty(message)) {
message = "登陆异常,请稍后重试!";
}
ToastUtil.show(this, message);
}
@Override
public void showNotice(String message) {
ToastUtil.show(this, message);
}
@Override
public void isCanClick(boolean canClick) {
if (canClick) {
loginLoginButton.setBackgroundResource(R.drawable.wb_login_btn_xml);
loginLoginButton.setClickable(canClick);
} else {
loginLoginButton.setBackgroundResource(R.drawable.wb_unlogin_btn_xml);
loginLoginButton.setClickable(canClick);
}
}
@Override
public void loadingDismiss() {
qianguiAccountLoading.statusToNormal();
qianguiAccountLoading.setVisibility(View.GONE);
}
@Override
}

以上的代码中删去了一部分和公司相关的字段和数据,只是给大家做一个示例,不要生搬硬套。v和m的书写完全看个人的业务需求。

当我们需要替换登陆页面,或者需要替换登陆方式时,这时就会发现我们只需要动View和model即可。p就可以完全保持不动。

如果大家有什么不理解的地方,也可以给我留言。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android MVP mvp mvc