前言:Android开发中有很多的设计模式,MVP模式无疑是现在最流行的模式之一。MVP模式有效的降低了项目的复杂性及耦合性,view与model间完全解耦,通过presenter作为中间的连接纽带,降低了view的复杂性及view与model耦合程度,使的项目逻辑更加清晰,方便后期的修改与维护。
MVP:Model--View--Presenter
model:用于数据的处理,如请求网络数据等
view:用于将presenter传递的数据在UI中展示
presenter:将model获取的数据传递给view,是view与model联系的中间桥梁
注:文中有用到Retrofit2+Rxjava2+Okhttp3实现网络数据请求相关的知识,这一篇文章 Android网络请求Retrofit2+Rxjava2+Okhttp3的简单封装中有详细介绍。
1.Model
(1)定义model基类接口
/**
* Created by ruancw on 2018/5/22.
* model接口基类
*/
public interface IBaseModel {
//获取Rxjava的disposable
Disposable getObservable(Observable> observable, String tag);
//网络请求接口回调
interface IOnRequestListener{
void onRequestSuccess(HttpResponse tHttpResponse, String tag);
void onRequestFail(Throwable throwable);
}
}
(2)定义model实现类
/**
* Created by ruancw on 2018/5/22.
* 通用model实现类
*/
public class CommonModelImpl implements IBaseModel {
private IOnRequestListener onRequestListener;
public CommonModelImpl(IOnRequestListener onRequestListener) {
this.onRequestListener = onRequestListener;
}
@Override
public Disposable getObservable(Observable> observable, String tag) {
return DisposableUtils.getDisposable(observable,tag,onRequestListener);
}
}
2.View
定义view接口类
/**
* Created by ruancw on 2018/5/22.
* view基类接口
*/
public interface IBaseView {
//显示默认的进度框
void showProgress();
//显示可设置提示信息的进度框
void showProgress(String message);
//隐藏进度框
void hideProgress();
//网络请求数据成功后返回数据的方法
void onSuccess(HttpResponse httpResponse, String tag);
//网络请求失败的方法
void onFailed(Throwable throwable);
}
3.Presenter
(1)定义presenter的基类
/**
* Created by ruancw on 2018/5/22.
* presenter基类
*/
public class BasePresenter implements IBaseModel.IOnRequestListener {
//view接口
protected IBaseView mView;
//model接口实现类
protected CommonModelImpl mModel;
//Rxjava中的类
private CompositeDisposable mCompositeDisposable;
/**
* 绑定view
* @param mView
*/
public void attach(IBaseView mView){
this.mView=mView;
mModel=new CommonModelImpl(this);
}
/**
* 解绑view
*/
public void detach(){
if (mView!=null){
mView=null;
}
}
/**
* 反注册rxjava
*/
public void unSubscribe(){
if (mCompositeDisposable != null) {
mCompositeDisposable.dispose();
}
}
/**
* 注册rxjava
* @param disposable
*/
public void addSubscription(Disposable disposable) {
//rxjava进行注册
if (mCompositeDisposable == null) {
mCompositeDisposable= new CompositeDisposable();
}
mCompositeDisposable.add(disposable);
}
@Override
public void onRequestSuccess(HttpResponse httpResponse, String tag) {
if (mView!=null){
mView.hideProgress();
mView.onSuccess(httpResponse,tag);
}
}
@Override
public void onRequestFail(Throwable throwable) {
if (mView!=null){
mView.hideProgress();
mView.onFailed(throwable);
}
}
}
(2)继承基类BasePresenter(以登录为例)
/**
* Created by ruancw on 2018/5/23.
* 登录的presenter实现类
*/
public class LoginPresenterImpl extends BasePresenter {
public void login(String url, LinkedHashMap paramsMap,String tag){
mView.showProgress("正在登录");
addSubscription(mModel.getObservable(HttpApiService.getInstance().getRemoteData(url,paramsMap),tag));
}
}
注:直接定义的LoginPresenter的实现类,没有定义ILoginPresenter接口
4.模块中使用
(1)定义Activity基类
public abstract class BaseMvpActivity extends BaseActivity {
public B mPresenter;
@Override
protected void beforeSetContentView() {
mPresenter=initPresenter();
mPresenter.attach(this);
}
protected abstract B initPresenter();
@Override
protected void onDestroy() {
mPresenter.detach();
//mPresenter.unSubscribe();
super.onDestroy();
}
}
(2)LoginActivity继承BaseMvpActivity
public class LoginActivity extends BaseMvpActivity {
@BindView(R.id.btn_login)
Button btnLogin;
@BindView(R.id.et_account)
ClearEditText etAccount;
@BindView(R.id.et_password)
PasswordView etPassword;
private int userType=1;
private UserBean userBean;
private boolean autoLogin; @Override
protected boolean hasHeadTitle() {
return false;
}
@Override
protected LoginPresenterImpl initPresenter() {
return new LoginPresenterImpl();
}
@Override
protected int getLayoutId() {
return R.layout.activity_login;
}
@Override
protected void initView() {
//获取上一次填写的用手机号与密码
userBean=SharePreferencesUtil.getInstance().getUserBean();
if (this.getIntent() != null && this.getIntent().getExtras() != null && this.getIntent().getExtras().containsKey("username")) {
String username = this.getIntent().getExtras().getString("username");
etAccount.setText(username);
} else {
if (userBean != null) {
etAccount.setText(userBean.getAccount());
etPassword.setContent(userBean.getPassword());
}
}
//判断是否是自动登录
autoLogin=SharePreferencesUtil.getInstance().getBoolean("AUTO_LOGIN");
if (autoLogin){
//自动登录
login();
}
}
/**
* 登录的方法
*/
private void login() {
etPassword.clearFocus();
//系统的输入管理器
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(etPassword, InputMethodManager.SHOW_FORCED);
imm.hideSoftInputFromWindow(etPassword.getWindowToken(), 0);
if (TextUtils.isEmpty(etAccount.getText().toString().trim())) {
UIUtil.toast("手机号不能为空");
} else if (TextUtils.isEmpty(etPassword.getContent().trim())) {
UIUtil.toast("密码不能为空");
} else {
LinkedHashMap paramsMap = new LinkedHashMap<>();
paramsMap.put("loginName", etAccount.getText().toString().trim());
paramsMap.put("password", etPassword.getContent().trim());
paramsMap.put("userType", userType + "");
mPresenter.login(ApiConstant.LOGIN, paramsMap, "tag");
}
}
@OnClick(R.id.btn_login)
public void onViewClicked() {
//点击的动画效果
CommonUtil.animateClickView(btnLogin, new CommonUtil.ClickAnimation() {
@Override
public void onClick(View v) {
login();
}
});
}
@Override
public void onSuccess(HttpResponse httpResponse, String tag) {
int code = httpResponse.getStatus();
Log.i("rcw", "httpResponse=" + httpResponse);
Log.i("rcw", "code=" + httpResponse.getStatus());
Log.i("rcw", "data=" + httpResponse.getData());
if (code == 200) {
//存储账号和密码
userBean=new UserBean();
userBean.setAccount(etAccount.getText().toString().trim());
userBean.setPassword(etPassword.getContent().trim());
userBean.setUsertype(userType);
SharePreferencesUtil.getInstance().saveUserBean(userBean);
//处理返回的data数据
String datas = new Gson().toJson(httpResponse.getData());
LoginBean loginBean = new Gson().fromJson(datas, LoginBean.class);
SharePreferencesUtil.getInstance().saveLoginBean(loginBean);
Log.i("rcw", "getDeptName=" + loginBean.getDeptName());
startActivity(new Intent(this, MainActivity.class));
finish();
UIUtil.toast("登录成功");
} else if (code == 402) {
exitToLogin(this);
} else {
UIUtil.toast(httpResponse.getMessage());
}
}
总结:MVP模式使得View与Model间不能直接交互,通过中间纽带Presenter实现间接联系,降低了View与Model间的耦合。MVP模式虽好,但如果项目页面相对简单,可以直接使用MVC模式实现。
如有任何问题,欢迎评论及留言,不胜感激,谢谢!!!