本文主要是介绍Android开发MVP模式浅谈,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
关键字:M:Model, V: View, C:Controllor, P:Presenter, IV:IView
说MVP之前先说说MVC模式。MVC其实就是Android默认开发模式,最多加过一个实体类(bean)
怎么说MVC就是Android默认开发模式呢,
因为M:实体类,基本不处理逻辑
V:xml,布局文件
C:对应Activity,处理逻辑(M,V它都可以参与)
弊端很明显:C端要处理逻辑,迟早一天会炸。
一定要把C端的逻辑处理(网络请求,复杂的数据运算等)解放出来,怎么办,那MVC模式就要进行改良优化,拆分C端的逻辑出来作为P,把C改为V端,P处理完用IView连接V和M。
针对MVP模式,大致可以这么划分:
M:实体类,
V:xml,Activity(不处理复杂逻辑,可以处理些简单的)
P:处理复杂的逻辑(网络请求)
IV:接口连接P和V的
说了怎么多,来看下代码比较的直观,以登录模块来说
先看下项目结构
写一个模块,肯定先写xml布局的,以为布局写法都差不多,就不展示了。
默认写了xml,接下来写bean类,我们来看下LoginResult(基本都是get和set方法);
public class LoginResult extends WebResult {private ObjBean obj;public ObjBean getObj() {return obj;}public void setObj(ObjBean obj) {this.obj = obj;}public static class ObjBean extends UserResume {}}
上面已经说了p与v交互是通过接口来操作的。下面来看下LoginIView接口
public interface LoginIView extends BaseActivityIView<LoginResult> {/*** 启用登陆按钮* Create by Peng on 2016年12月8日10:50:01*/void enableBtn();/*** 登录成后* Create by Peng on 2016年12月8日10:50:01*/void onData(LoginResult result);/*** 授权登录跳转进MainActivity* Create by cong*/void authorizeSuccess(LoginResult result);/*** 授权登录跳转进验证手机号*/void authorizePhone(LoginResult result);
}
接下来写Presenter。也可以先写Activity。看个人习惯思维,有些人想先看下界面,界面通过了,再加逻辑。我很多情况也先写Activity,上面有操作按钮,要数据传到Presenter中处理,也是合理的。但你说先写Presenter也行,毕竟都是形参方法。
public class LoginPresenter {private static final String TAG = LoginPresenter.class.getName();private LoginIView iView;private String time = "";public LoginPresenter(LoginIView iView) {this.iView = iView;}/*** 登录* @param phone 手机号* @param pass 密码*/public void login(String phone, String pass) {if (TextUtils.isEmpty(phone)) {iView.toast(R.string.phone_error);iView.enableBtn();return;}if (TextUtils.isEmpty(pass)) {iView.toast(R.string.pass_error);iView.enableBtn();return;}try {iView.showProgressDialog(R.string.loging);HashMap<String, Object> map = new HashMap<>();map.put("phone", phone);map.put("psw", AES128ECB.Encrypt(pass, AES128ECB.cKey));HttpUtils.noCacheRequest(iView.getContext(), Contacts.LOGIN, map, callBack, LoginResult.class);time = map.get("timestamp").toString();} catch (Exception e) {e.printStackTrace();if (BuildConfig.DEBUG) {iView.toast(R.string.error);}iView.enableBtn();}}/*** 登录的回调* Create by Peng*/private ResponseCallBack callBack = new ResponseCallBack<LoginResult>() {@Overridepublic void onError(int code, Throwable e) {iView.toast(R.string.request_error);iView.dismissProgressDialog();iView.enableBtn();e.printStackTrace();}@Overridepublic void onCache(LoginResult cache) {}@Overridepublic void onResponse(LoginResult obj) {if (obj.getCode() == 1) {//登录成功iView.onData(obj);iView.toast("登录成功");} else {iView.toast(obj.getMsg());}iView.enableBtn();iView.dismissProgressDialog();}@Overridepublic void onFinish() {}};
}
上面代码中有访问网络逻辑,用iView接口与Activity数据交互
最后来看下Activity。也是大家所熟悉的,也有点不通,构造上复杂了点而已。
public class LoginActivity extends BaseActivity implements LoginIView {@BindView(R.id.et_phone_number)EditText et_phone_number;@BindView(R.id.et_pass)EditText et_pass;@BindView(R.id.btn_login)Button btn_login;@BindView(R.id.cb_pass_show)CheckBox cb_pass_show;@BindView(R.id.tv_one_yuan_user_agreement)TextView tv_one_yuan_user_agreement;@BindView(R.id.btn_res)Button btn_res;@BindView(R.id.btn_look)Button btn_look;@BindView(R.id.tv_forget_pass)TextView tv_forget_pass;@BindView(R.id.ll_wx_login)LinearLayout llWxLogin;private Context mContext;private LoginPresenter presenter;private int userId;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);ButterKnife.bind(this);mContext = this;et_pass.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);et_pass.setTransformationMethod(PasswordTransformationMethod.getInstance());et_phone_number.setText(SharedPreferencesUtils.getString(this, Contacts.PHONE, ""));et_phone_number.setSelection(et_phone_number.getText().length());presenter = new LoginPresenter(this);}@Overrideprotected void initRealView(View view) {}@Overrideprotected void errorClick() {}public boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK) {//do something...ActivityUtils.closeAll();finish();return true;}return super.onKeyDown(keyCode, event);}@OnClick({R.id.btn_login, R.id.tv_one_yuan_user_agreement, R.id.btn_res, R.id.btn_look, R.id.tv_forget_pass, R.id.ll_wx_login})public void onClick(View view) {view.setEnabled(false);Intent intent = null;switch (view.getId()) {//登陆按钮case R.id.btn_login:view.setEnabled(false);if (valiData()) {
// presenter.regist(et_phone_number.getText().toString(), et_security_code.getText().toString(),
// et_pass.getText().toString());//先清理缓存HttpUtils.clearCache(MyApplication.getContext());SharedPreferencesUtils.clear(MyApplication.getContext());SharedPreferencesUtils.saveBoolean(this, Contacts.GUIDE, false);SharedPreferencesUtils.saveString(this, Contacts.PHONE, et_phone_number.getText().toString());presenter.login(et_phone_number.getText().toString(), et_pass.getText().toString());} else {view.setEnabled(true);}break;//注册账号case R.id.btn_res:UtilsIntent.startRegisterActivity(this, 0, 0);break;//先看看case R.id.btn_look://进入主页面UtilsIntent.startMainActivity(mContext);break;//忘记密码case R.id.tv_forget_pass:intent = new Intent(this, ForgetPassActivity.class);startActivity(intent);view.setEnabled(true);break;//用户协议跳转case R.id.tv_one_yuan_user_agreement:UtilsIntent.startWebActivity2(view.getContext());break;}view.setEnabled(true);}/*** 验证数据是否输入完整* Create by Peng on 2016年12月8日16:53:00** @return 是否完整*/private boolean valiData() {if (StringUtils.isEmpty(et_phone_number)) {toast(R.string.phone_error);return false;}SharedPreferencesUtils.saveString(this, Contacts.PHONE, et_phone_number.getText().toString());if (StringUtils.isEmpty(et_pass)) {toast(R.string.pass_error);return false;}if (et_pass.getText().toString().length() < 6) {toast(R.string.pass_error1);return false;}return true;}//显示隐藏密码的按钮@OnCheckedChanged(R.id.cb_pass_show)public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {if (isChecked) {//显示密码et_pass.setTransformationMethod(HideReturnsTransformationMethod.getInstance());et_pass.setSelection(et_pass.getText().length());} else {//隐藏密码et_pass.setTransformationMethod(PasswordTransformationMethod.getInstance());et_pass.setSelection(et_pass.getText().length());}}@Overridepublic void enableBtn() {btn_login.setEnabled(true);}@Overridepublic void onData(LoginResult result2) {if(result2.getObj() != null){SharedPreferencesUtils.saveInt(this, Contacts.USERID, result2.getObj().getId());try {Utils.saveUserResume(this, result2.getObj());MainActivity.toMain(this, true);} catch (Exception e) {e.printStackTrace();if (BuildConfig.DEBUG) {toast(R.string.error);}}}}@Overridepublic void onDataResult(LoginResult loginResult) {SharedPreferencesUtils.saveInt(this, Contacts.USERID, loginResult.getObj().getId());try {Utils.saveUserResume(this, loginResult.getObj());MainActivity.toMain(this, true);} catch (Exception e) {e.printStackTrace();if (BuildConfig.DEBUG) {toast(R.string.error);}}}
}
注:以上代码仅供参考,因为有些牵扯到瓦的项目,省去了。
MVP模式更容易排除,比如网络请求数据有错,只需要看P,请求到有数据,但页面没显示,看V是否赋值显示或者看M,是否已经定义该属性set和get方法。
用MVP后基本不再想用MVC,不好的哇,估计多了个前期的学习成本
这篇关于Android开发MVP模式浅谈的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!