前言: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 { <T>Disposable getObservable(Observable<HttpResponse<T>> observable, String tag); //网络请求接口回调 interface IOnRequestListener<T>{ void onRequestSuccess(HttpResponse<T> 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 <T> Disposable getObservable(Observable<HttpResponse<T>> 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<String, String> paramsMap,String tag){ mView.showProgress("正在登录"); addSubscription(mModel.getObservable(HttpApiService.getInstance().getRemoteData(url,paramsMap),tag)); } }
注:直接定义的LoginPresenter的实现类,没有定义ILoginPresenter接口
4.模块中使用
(1)定义Activity基类
public abstract class BaseMvpActivity<B extends BasePresenter> 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<LoginPresenterImpl> { @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())) { //etAccount.setError("手机号不能为空"); UIUtil.toast("手机号不能为空"); } else if (TextUtils.isEmpty(etPassword.getContent().trim())) { //etAccount.setError("手机号不能为空"); UIUtil.toast("密码不能为空"); } else { LinkedHashMap<String, String> 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); 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模式实现。
如有任何问题,欢迎评论及留言,不胜感激,谢谢!!!