Android开发MVP模式浅谈

2024-05-05 06:32
文章标签 android 模式 开发 浅谈 mvp

本文主要是介绍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模式浅谈的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/961005

相关文章

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

SpringBoot开发中十大常见陷阱深度解析与避坑指南

《SpringBoot开发中十大常见陷阱深度解析与避坑指南》在SpringBoot的开发过程中,即使是经验丰富的开发者也难免会遇到各种棘手的问题,本文将针对SpringBoot开发中十大常见的“坑... 目录引言一、配置总出错?是不是同时用了.properties和.yml?二、换个位置配置就失效?搞清楚加

Android DataBinding 与 MVVM使用详解

《AndroidDataBinding与MVVM使用详解》本文介绍AndroidDataBinding库,其通过绑定UI组件与数据源实现自动更新,支持双向绑定和逻辑运算,减少模板代码,结合MV... 目录一、DataBinding 核心概念二、配置与基础使用1. 启用 DataBinding 2. 基础布局

Python中对FFmpeg封装开发库FFmpy详解

《Python中对FFmpeg封装开发库FFmpy详解》:本文主要介绍Python中对FFmpeg封装开发库FFmpy,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、FFmpy简介与安装1.1 FFmpy概述1.2 安装方法二、FFmpy核心类与方法2.1 FF

Android ViewBinding使用流程

《AndroidViewBinding使用流程》AndroidViewBinding是Jetpack组件,替代findViewById,提供类型安全、空安全和编译时检查,代码简洁且性能优化,相比Da... 目录一、核心概念二、ViewBinding优点三、使用流程1. 启用 ViewBinding (模块级

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

Redis Cluster模式配置

《RedisCluster模式配置》:本文主要介绍RedisCluster模式配置,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录分片 一、分片的本质与核心价值二、分片实现方案对比 ‌三、分片算法详解1. ‌范围分片(顺序分片)‌2. ‌哈希分片3. ‌虚

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

使用Python开发一个现代化屏幕取色器

《使用Python开发一个现代化屏幕取色器》在UI设计、网页开发等场景中,颜色拾取是高频需求,:本文主要介绍如何使用Python开发一个现代化屏幕取色器,有需要的小伙伴可以参考一下... 目录一、项目概述二、核心功能解析2.1 实时颜色追踪2.2 智能颜色显示三、效果展示四、实现步骤详解4.1 环境配置4.