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

相关文章

如何开启和关闭3GB模式

https://jingyan.baidu.com/article/4d58d5414dfc2f9dd4e9c082.html

十四、观察者模式与访问者模式详解

21.观察者模式 21.1.课程目标 1、 掌握观察者模式和访问者模式的应用场景。 2、 掌握观察者模式在具体业务场景中的应用。 3、 了解访问者模式的双分派。 4、 观察者模式和访问者模式的优、缺点。 21.2.内容定位 1、 有 Swing开发经验的人群更容易理解观察者模式。 2、 访问者模式被称为最复杂的设计模式。 21.3.观察者模式 观 察 者 模 式 ( Obser

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

android 免费短信验证功能

没有太复杂的使用的话,功能实现比较简单粗暴。 在www.mob.com网站中可以申请使用免费短信验证功能。 步骤: 1.注册登录。 2.选择“短信验证码SDK” 3.下载对应的sdk包,我这是选studio的。 4.从头像那进入后台并创建短信验证应用,获取到key跟secret 5.根据技术文档操作(initSDK方法写在setContentView上面) 6.关键:在有用到的Mo

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

Android我的二维码扫描功能发展史(完整)

最近在研究下二维码扫描功能,跟据从网上查阅的资料到自己勉强已实现扫描功能来一一介绍我的二维码扫描功能实现的发展历程: 首页通过网络搜索发现做android二维码扫描功能看去都是基于google的ZXing项目开发。 2、搜索怎么使用ZXing实现自己的二维码扫描:从网上下载ZXing-2.2.zip以及core-2.2-source.jar文件,分别解压两个文件。然后把.jar解压出来的整个c

android 带与不带logo的二维码生成

该代码基于ZXing项目,这个网上能下载得到。 定义的控件以及属性: public static final int SCAN_CODE = 1;private ImageView iv;private EditText et;private Button qr_btn,add_logo;private Bitmap logo,bitmap,bmp; //logo图标private st

Android多线程下载见解

通过for循环开启N个线程,这是多线程,但每次循环都new一个线程肯定很耗内存的。那可以改用线程池来。 就以我个人对多线程下载的理解是开启一个线程后: 1.通过HttpUrlConnection对象获取要下载文件的总长度 2.通过RandomAccessFile流对象在本地创建一个跟远程文件长度一样大小的空文件。 3.通过文件总长度/线程个数=得到每个线程大概要下载的量(线程块大小)。

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa