Android MVP模式简单介绍:以一个登陆流程为例

老的项目用的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:觉得看了还是不太明白或是好像明白的同学可以自己亲自动手写一写,应该写完就完全可以明白了。

原文地址:https://www.cnblogs.com/slma/p/9510741.html

时间: 2025-01-07 13:36:25

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

android MVP模式简单介绍

原文 http://zhengxiaopeng.com/2015/02/06/Android%E4%B8%AD%E7%9A%84MVP/ 前言 MVP作为一种MVC的演化版本在Android开发中受到了越来越多的关注,但在项目开发中选择一种这样的软件设计模式需保持慎重心态,一旦确定 使用MVP作为你App的开发模式那么你就最好坚持做下去,如果在使用MVP模式开发过程中发现问题而且坑越来越大,这时你想用MVC等来重新设计的话基 本上就等于推倒重来了.要知道在Android上MVP在现在为止并没有统

Android MVP模式学习(二)----Data Binding结合

公司项目最近已经用MVP模式重新构造完成,重构后的项目直观明了,代码复用性高,易于调试维护. 之后主管让我去了解MVC,MVP ,MVVM,Data Binding相关的知识,于是便有了下面这篇博客.参考资料: 选择恐惧症的福音!教你认清MVC,MVP和MVVM 完全掌握Android Data Binding 这里很感谢这两篇文章的理论与技术支持,感谢这些大神. OK,开始今天的主题. 关于MVP模式与MVVM模式孰是孰非,我想不是我一个初学者短短几句就能够说清楚的,我们也不用纠结于此.引用大

android mvp高速开发框架介绍(dileber的简单介绍)

今天我为大家介绍一款android mvp框架:dileber(https://github.com/dileber/dileber.git) 官方交流qq群:171443726 我个人qq:297165331--有什么问题也能够咨询-- ss 随着对安卓开发的深入.越来越发现activity类简直无所不能,于是就导致activity里的代码太多,让人感觉很不爽. 近年来開始流行mvp.于是我对其进行了解,学习,參照了一些资料.自己整合了一套高速开发框架. 我将google 开发的volley,

Android架构篇--MVP模式的介绍篇

摘要: 在MVVM成熟之前MVP模式在Android上有被神化的趋势,笔者曾经在商业项目中从零开始大规模采用过MVP模式对项目进行开发.在使用MVP模式进行开发的时候发现项目的结构模式对开发是有一定的影响的,在这里笔者会对这一问题进行探讨.希望通过这篇blog能让读者了解如何使用MVP模式搭建一个功能完善的MVP模式开发框架,避免一些笔者认为比较严重的问题. 为什么要使用MVP模式 在传统的Android开发中,我们一般是使用MVC模式进行开发的.传统MVC模式介绍: View: 视图层,对应x

作为过来人,对于Android MVP模式的一些详解

前言 闲来无事在家偶然翻到了之前整理的文档和面试要做到准备路线,虽然内容有点多,但是技多不压身,多多益善 本部分内容是关于Android进阶的一些知识总结,涉及到的知识点比较杂,不过都 是面试中几乎常问的知识点,也是加分的点. 关于这部分内容,可能需要有一些具体的项目实践.在面试的过程中,结合具体自 身实践经历,才能更加深入透彻的描绘出来 相关内容后续GitHub更新,想冲击金三银四的小伙伴可以找找看看,欢迎star(顺手留下GitHub链接,需要获取相关面试等内容的可以自己去找)https:/

关于Android MVP模式的思考

最近经常看到各种介绍MVP模式的博客的,之前写过不少的Android应用,在做那些应用的时候,都是要求快速完成,所以从开始设计到写代码就一直考虑着重用.以前写的项目基本都是不断重构项目,将项目代码变得更加精简,提高代码之间的复用性.但是代码并没有特别地注重按照MVC模式或者是MVP模式来,更多的是直接考虑模块化,重用,精简.所以看了MVP模式后,决定去总结一下自己代码中的问题并优化,算是对自己之前写的代码的回顾. MVP框架 MVP框架是目前在Android流行起来的框架,它非常适合用于Andr

Xamarin.Android MVP模式

一.简介 随着UI创建技术的功能日益增强,UI层也履行着越来越多的职责.为了更好地细分视图(View)与模型(Model)的功能,让View专注于处理数 据的可视化以及与用户的交互,同时让Model只关系数据的处理,基于MVC概念的MVP(Model-View-Presenter)模式应运而生. 在MVP模式里通常包含4个要素: View:负责绘制UI元素.与用户进行交互(在Android中体现为Activity); View interface:需要View实现的接口,View通过View i

android MVP模式思考

在软件开发设计中,有多种软件设计模式,如web开发中经典的MVC, 将后台分为三层:Model层,View层和Controller层,其中,Model主要是数据处理,如数据库,文件,或网络数据等:View层是视图层,主要是指前端或后端用于直接展现给用户的页面,Controller层则是负责业务逻辑处理,即将Model中读取的数据显示到View层,同时又将View层触发的操作事件经过业务处理后将数据保存到Model层中. 在android中,可能很多开发者使用的还是mvc模式,比如,在代码中可以发

Objective-C 原型模式 -- 简单介绍和使用

先借鉴百科对原型模式的介绍: 定义: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. Prototype原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建. 解决什么问题: 它主要面对的问题是:"某些结构复杂的对象"的创建工作:由于需求的变化,这些对象经常面临着剧烈的变化,但是他们却