老的项目用的MVC的模式,最近完成了全部重构成MVP模式的工作,虽然比较麻烦,好处是代码逻辑更加清楚、简洁,流程更加清晰,对于后续版本迭代维护都挺方便。
对于一些想要学习MVP模式的同学来讲,百度搜出来的好多都没法直接转化为项目里可以直接用的东西,所以这里正好拿出自己项目里已经用了的,你们可以直接用到自己的项目里。当然,不可能把所有项目代码在这里放出来,所以就拿登陆的流程出来,这个比较合适也比较常用。

1、先看下包结构:

model:放一些bean类,以及网络处理类RetrofitManager,ServiceHelper(封装的网络请求类)等

view:放UI层需要实现的逻辑

presenter:放一些业务逻辑相关的接口及实现类

 2、进入正题

首先,以登陆流程为例,简单画下流程图:

然后开始划分对应三个层的逻辑:

presenter:作为登录页面,涉及的业务逻辑有:记住密码,登录,保存登录之后获取的Token

public interface ILoginPresenter {
void rememberPassword(String account,String pwd);
void login(String phoneNum,String pwd);
void saveToken(String token);
}

LoginPresenterImpl:负责具体登陆逻辑及view层业务的调用,持有view层对象引用:iLoginView

public class LoginPresenterImpl implements ILoginPresenter {
private static final String TAG = "LoginPresenterImpl"; private String mMd5Pwd;
ILoginView mILoginView; private Context mContext; public LoginPresenterImpl(ILoginView iLoginView, Context context) {
this.mILoginView = iLoginView;
this.mContext = context;
} @Override
public void rememberPassword(String account, String pwd) {
SPUtils.put(mContext, "remember_password", true);
SPUtils.put(mContext, "phoneNum", account);
SPUtils.put(mContext, "password", pwd);
} @Override
public void login(String phoneNum, String pwd) {
if (TextUtils.isEmpty(phoneNum)) {
mILoginView.loginResult(false, Constant.PHONENUM_NULL);return;
} if (!Utils.isMobileNO(phoneNum)) {
mILoginView.loginResult(false, Constant.PHONENUM_FALSE);return;
} if (TextUtils.isEmpty(pwd)) {
mILoginView.loginResult(false, Constant.PWD_NULL);return;
} mMd5Pwd = Utils.encrypt(pwd);
LogUtils.d(TAG, "pwd:" + pwd + "------------ mMd5Pwd:" + mMd5Pwd); //判断网络是否可用
if (!Utils.isNetAvail()) {
mILoginView.loginResult(false, Constant.INTERNET_FAILED);
LogUtils.d(TAG, "网络不可用");
return;
} //发起网络请求,查看手机号和密码是否正确
ServiceHelper.callEntity(RetrofitManager.getInstance().createReq(Login.class).getLoginData(phoneNum, mMd5Pwd), LoginBean.class, new OnResponseLisner<LoginBean>() {
@Override
public void onSuccess(LoginBean info) {
int mUid = info.getData().getUID();
String token = info.getData().getToken();
saveToken(token); mILoginView.loginResult(true, String.valueOf(mUid));
} @Override
public void onError(String errorMsg) {
mILoginView.loginResult(false, errorMsg);
}
});
} @Override
public void saveToken(String token) {
if (!TextUtils.isEmpty(token)) {
//存储String值
SPUtils.put(mContext, "Token", token);
}
}

view:登陆结果的处理展示(由具体实现类MainActivity实现对应的方法)

public interface ILoginView {
void loginResult(Boolean result, String msg);
}

model:服务器返回的数据bean类

public class LoginBean {
public boolean Success;
public int Code;
public String ErrorMsg_zh;
public String ErrorMsg_en;
public DataBean Data;
public int ServerTime;
public String LogId; public static class DataBean {
public int UID;
public String Name;
public String Phone;
public String Email;
public String FacePic;
public String Token; }

最后,看下完整的登陆页面MainActivity(ILoginView实现类)的代码:

public class LoginActivity extends BaseActivity implements ILoginView {

    @BindView(R.id.et_phoneNum)
EditText mEtPhoneNum; @BindView(R.id.et_pwd)
EditText mEtPwd; @BindView(R.id.iv_phoneNumClear)
ImageView mPhoneNumClear; @BindView(R.id.iv_pwdClear)
ImageView mPwdClear; @BindView(R.id.cb_checkbox)
CheckBox mCheckBox; @BindView(R.id.btn_login)
Button mBtnLogin; @BindView(R.id.avi_loading)
AVLoadingIndicatorView mAviLoading; private String TAG = "LoginActivity";
private String mPhoneNum;
private String mPwd;
private ILoginPresenter mILoginPresenter; @Override
public int getLayoutResId() {
return R.layout.activity_login;
} @Override
protected void init() {
super.init(); mILoginPresenter = new LoginPresenterImpl(this, LoginActivity.this); boolean isRemenber = (boolean) SPUtils.get(this, "remember_password", false);
LogUtils.d(TAG, "isRemenber:" + isRemenber); if (isRemenber) {
//将账号和密码都设置到文本中
String account = (String) SPUtils.get(this, "phoneNum", "");
String password = (String) SPUtils.get(this, "password", ""); mEtPhoneNum.setText(account);
mEtPwd.setText(password);
mCheckBox.setChecked(true); } mBtnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) { mAviLoading.setVisibility(View.VISIBLE); mPhoneNum = mEtPhoneNum.getText().toString().trim();
mPwd = mEtPwd.getText().toString().trim(); mILoginPresenter.login(mPhoneNum, mPwd);
if (mCheckBox.isChecked()) {
mILoginPresenter.rememberPassword(mPhoneNum, mPwd);
} else {
SPUtils.remove(LoginActivity.this, "remember_password");
SPUtils.remove(LoginActivity.this, "phoneNum");
SPUtils.remove(LoginActivity.this, "password");
}
}
});
} @Override
public void loginResult(Boolean result, String msg) {
if (result) {
LogUtils.d(TAG, "uid:" + msg);
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("uid", msg);
startActivity(intent);
} else {
CustomToast.show(this, msg + " 请稍后再试!");
}
mAviLoading.setVisibility(View.INVISIBLE);
}

3、总结,MVP结构图:

view层和Presenter层互相持有对方的引用,model只会被presenter层使用。

PS:觉得看了还是不太明白或是好像明白的同学可以自己亲自动手写一写,应该写完就完全可以明白了。

Android MVP模式简单介绍:以一个登陆流程为例的更多相关文章

  1. android MVP模式简单介绍

    原文 http://zhengxiaopeng.com/2015/02/06/Android%E4%B8%AD%E7%9A%84MVP/ 前言 MVP作为一种MVC的演化版本在Android开发中受到 ...

  2. Android MVP模式简单易懂的介绍方式 (一)

    Android MVP模式简单易懂的介绍方式 (一) Android MVP模式简单易懂的介绍方式 (二) Android MVP模式简单易懂的介绍方式 (三) 最近正在研究Android的MVP模式 ...

  3. Android MVP模式简单易懂的介绍方式 (三)

    Android MVP模式简单易懂的介绍方式 (一) Android MVP模式简单易懂的介绍方式 (二) Android MVP模式简单易懂的介绍方式 (三) 讲完M和P,接下来就要讲V了.View ...

  4. Android MVP模式简单易懂的介绍方式 (二)

    Android MVP模式简单易懂的介绍方式 (一) Android MVP模式简单易懂的介绍方式 (二) Android MVP模式简单易懂的介绍方式 (三) 上一篇文章我们介绍完了Model的创建 ...

  5. Android MVP模式 简单易懂的介绍方式

    主要学习这位大神的博客:简而易懂 Android MVP模式 简单易懂的介绍方式 https://segmentfault.com/a/1190000003927200

  6. Android MVP模式

    转自http://segmentfault.com/blogs,转载请注明出处Android MVP Pattern Android MVP模式\[1\]也不是什么新鲜的东西了,我在自己的项目里也普遍 ...

  7. android MVP模式介绍与实战

    android MVP模式介绍与实战 描述 MVP模式是什么?MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数 ...

  8. MVP 模式简单易懂的介绍方式

    为什么用Android MVP 设计模式? 当项目越来越庞大.复杂,参与的研发人员越来越多的时候,MVP 模式 的优势就充分显示出来了. MVP 模式是 MVC 模式在 Android 上的一种变体, ...

  9. Android MVP模式 谷歌官方代码解读

    Google官方MVP Sample代码解读 关于Android程序的构架, 当前(2016.10)最流行的模式即为MVP模式, Google官方提供了Sample代码来展示这种模式的用法. Repo ...

随机推荐

  1. python文件读取,替换(带格式,python lib 库)

    import os, time import sys import re def read_old_part(filename, start, end): content = [] recording ...

  2. swift修饰符

    Declaration Modifiers Declaration modifiers are keywords or context-sensitive keywords that modify t ...

  3. Eclipse中将java类打成jar包形式运行

    记录一次帮助小伙伴将java类打成jar包运行 1.创建java project项目 file > new > project > java project 随便起一个项目名称,fi ...

  4. 8.学习springmvc的拦截器

    一.springmvc拦截器介绍和环境搭建 1.介绍: 过滤器:servlet中的一部分,可以拦截所有想要访问的资源. 拦截器:SpringMVC框架中的,只能在SpringMVC中使用并且只能过滤控 ...

  5. 解决mysql无法显示中文/MySQL中文乱码问号等问题

    一般都是编码格式问题 显示编码格式: show variables like'character_set_%'; 将其中Value不是utf8的改为utf8: set character_set_cl ...

  6. Spring整合MyBatis整合

    1.导入所需要的jar依赖 !--MyBatis和Spring的整合包 由MyBatis提供--> <dependency> <groupId>org.mybatis&l ...

  7. python:UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

    # 将默认编码设为utf-8 # 否则会报错: # UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ...

  8. 淘宝接口-IP返回运营商

    #!/usr/bin/evn python# -*- coding:utf-8 -*-import jsonimport urllib2import datetimeimport reimport Q ...

  9. [技术博客]JSCover+selenium获得js代码覆盖率

    本文档讲解了我们是如何使用JSCover来获得Selenium的测试样例的js代码文件的执行覆盖率的. 事实上网上有挺多博客讲这玩意儿了,不过完全按照网上已有的教程去弄的的话,并无法满足我们的需要. ...

  10. eclipse无法访问sun.misc.Unsafe类的解决办法

    参考:https://www.cnblogs.com/duanxz/p/6090442.html