Android中的MVP架构初探

说来惭愧,MVP的架构模式已经在Android领域出现一两年了,但是到今天自己才开始Android领域中的MVP架构征程。闲话不多说,开始吧!

一、架构演变概述

我记得我找第一份工作时,面试官问我“android是否属于MVC架构模式,简述一下”。确实,Android的整体设计结构就是MVC的设计模式,在J2EE的开发中,使用的也是MVC模式,MVC模式是一个经典,经历了几十年的考验。Android项目中的MVC架构:

  • View:是应用程序中处理数据显示的部分,对应于layout文件下的布局文件
  • Model:业务逻辑和实体模型
  • Controllor:是应用程序中处理用户交互的部分,Activity来充当。

看似分工明确,但是也给我们带来了不少问题,如果一个页面的业务逻辑非常复杂,我们的Activty需要大量的逻辑处理代码,使得Activity既像View又像Controllor,又当爹又当妈,工作量非常大。造成代码的阅读星非常差。

为了解决这个问题,MVP模式就在Android领域诞生了。补充:我查看资料发现MVP模式最早是微软设计出来的,应用在Visual Stuido平台,不得不说微软虽然闭源,但是很niubility。

二、MVP概述

上面的图,精炼的概述了MVP架构之间的通讯流程,在android中。

  • 模型(Model):业务逻辑处理,负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等;
  • 视图(View):负责界面数据的展示,与用户进行交互,就是Activity;
  • 主导器(Presenter):相当于协调者,是模型与视图之间的桥梁,将模型与视图分离开来。通过Presenter进行它们之间的交互,隔离了M、V之间的直接交互。

这样的架构,就让我们的Activity更像View,降低了M、V之间的耦合度。

三、MVP实践

我们先看下我们的效果图:

这是一个简答的登陆页面,在这个登陆页面中,我们就触发一个事件,就是点击登陆事件。我们先看看我们的工程组织架构。

我们分别创建了:bean、model、presenter、view四个包,为了解放Activity,我们把以前Activity里的大量逻辑进行拆分。

1、bean包

我们创建实体UserBean,用来存放我们的用户信息,这个没什么说的。

    public class UserBean implements Parcelable{
        private String name;
        private String password;

        public UserBean(){

        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }

        @Override
        public int describeContents() {
            return 0;
        }
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(name);
            dest.writeString(password);
        }
    }

2、view包

我们首先从View(视图层)看,view包下存放了我们视图层中的操作,它不涉及任何业务逻辑,主要是针对我们的页面进行数据的获取与设置。我们针对这个登陆功能,进行分析:

  • 姓名和密码的获取
  • 姓名和密码的保存

我们抽取出页面View层需要做的事情,接下来我们定义一个IUserView接口,里面包含我们抽取出来的方法。

    /**
     * 抽离View层,用于View页面的数据获取之类
     * @author Administrator
     *
     */
    public interface IUserView {
        public String getUserName();
        public String getUserPsd();
    }

我们只进行了获取,没有做保存。总结:View层的任务就是抽象页面的数据,提取出来写成方法。

3、model包

在view层,我们的数据获取有了着落,现在我们就开始处理我们的业务逻辑。根据页面得知,我们就模拟一个登陆功能,所以它就一个登陆事件。我们创建IUserModel接口用于包含我们处理的业务逻辑。

    /**
     * 业务逻辑处理
     * @author Administrator
     *
     */
    public interface IUserModel {
        /**
         *提取的一个登陆方法,当然还可以有其它方法,比如获取数据,保存用户信息之类
         * @param name  用户名
         * @param pwd   密码
         * @param loginListener 登陆监听
         */
        public void login(String name,String pwd,ILoginListener loginListener);
    }

有了业务逻辑的接口规范,我们还需要去实现它,给与我们想要的逻辑。所以就有了UserModel类:

    public class UserModel implements IUserModel{

        @Override
        public void login(String name, String pwd, ILoginListener loginListener) {
            if(TextUtils.isEmpty(name) || TextUtils.isEmpty(pwd)){
                loginListener.onError();
                return;
            }

            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if("dsw".equals(name) && "123".equals(pwd)){
                loginListener.onSucess();
            }else{
                loginListener.onFail();
            }
        }
    }

我们为了方便我们对业务逻辑处理的监听,所以我们创建了一个接口,用来判断我们的登陆事件。

    /**
     * 登陆接口的监听,方便我们在View层中控制,便于给出提示
     * @author Administrator
     *
     */
    public interface ILoginListener {
        //登陆成功
        public void onSucess();
        //登陆失败
        public void onFail();
        //数据不完成
        public void onError();
    }

我们用来监听业务处理的判断,比如成功了我们弹出一个Toast之类的。

4、presenter包

数据有了,对数据的业务处理也有了,这里我们的Presenter就闪灵登场了。记住是Presenter、Presenter、Presenter(重要的东西说三次)。它用来连接我们的M、V层,让二者打通任督二脉实现整个流程。所以为了实现二者的联系,它的内部必然会有M、V的实例。来看看IUserPresenter:

    public class IUserPresenter {
        //数据源
        private IUserView userView;
        //处理业务逻辑
        private IUserModel userModel;

        public IUserPresenter(IUserView userView){
            this.userView = userView;
            userModel = new UserModel();
        }

        /**
         * 登陆方法,进行M,V层的关系建立
         * @param loginListener
         */
        public void login(ILoginListener loginListener){
            userModel.login(userView.getUserName(), userView.getUserPsd(), loginListener);
        }
    }

我们只需要在Activity中创建一个IUserPresenter类,然后调用login方法进行登录即可。在这段代码中,IUserView是我们的数据源,我们通过它的方法用于从页面获取数据,所以我们的Activity必须实现这个IUserView接口,然后传递给IUserPresenter。在IUserPresenter中调用IUserModel的实现业务逻辑的处理。

5、最后的Activity处理

    public class MainActivity extends Activity implements IUserView {
        private EditText et_name,et_pwd;
        private Button btn_login;
        //指示器与View层进行交互
        private IUserPresenter userPresenter;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            et_name = (EditText) findViewById(R.id.et_name);
            et_pwd = (EditText) findViewById(R.id.et_psw);
            btn_login = (Button) findViewById(R.id.btn_login);
            userPresenter = new IUserPresenter(this);
            btn_login.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    userPresenter.login(loginListener);
                }
            });
        }
        @Override
        public String getUserName() {
            return et_name.getText().toString();
        }
        @Override
        public String getUserPsd() {
            return et_pwd.getText().toString();
        }

        /**
         * 登陆监听接口
         */
        private ILoginListener loginListener = new ILoginListener() {

            @Override
            public void onSucess() {
                Toast.makeText(getApplication(), "登陆成功", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onFail() {
                Toast.makeText(getApplication(), "登陆失败", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onError() {
                Toast.makeText(getApplication(), "数据不完整,请重新输入", Toast.LENGTH_SHORT).show();
            }
        };
    }

在activity中,我们实现IUserView接口,来实现该view层的数据获取。然后创建IUserPresenter类,调用login方法进行登录。同时实现对业务逻辑的处理监听。

至此,我们就完成了整个的流程,看看我们的效果图:

强烈建议大家手动敲一遍代码,加深理解。

总结图:

==========================================================

作者:mr_dsw

转载注明出处,分享是进步的源泉。

==========================================================

时间: 2024-08-28 21:02:48

Android中的MVP架构初探的相关文章

Android中的MVP架构

Android应用的MVC架构,Activity往往充当了View和Control双重角色,造成代码耦合性较强.怎样将View和Control解耦呢,可以使用MVP架构(Model.Control.Prestener)将Activity的View和Control彻底分离,不说废话了直接上代码吧! github: https://github.com/Allin1579/Allin-android 以Activity为例,Fragment的原理相同: View:我们将Activity看作一个单纯的

Android开发中的MVP架构(转)

写在前面,本博客来源于公众号文章:http://mp.weixin.qq.com/s?__biz=MzA3MDMyMjkzNg==&mid=402435540&idx=1&sn=1cd10bd9efaac7083575367a8b4af52f&scene=1&srcid=0910ARzPpBvVYPI1NDBZnixa#wechat_redirect 最近越来越多的人开始谈论架构.我周围的同事和工程师也是如此.尽管我还不是特别深入理解MVP和DDD,但是我们的新项目

浅谈Android中的MVP

转载请标明出处: http://blog.csdn.net/hai_qing_xu_kong/article/details/51745798 本文出自:[顾林海的博客] 前言 为什么使用MVP,网上有很多说法,最主要就是减轻了Activity的责任,相比于MVC中的Activity承担的责任太多,因此有必要讲讲MVP. MVP入门 在MVC框架中,View是可以直接读取Model模型中的数据的,Model模型数据发生改变是会通知View数据显示发生相应的改变.而在MVP中Model和View之

如何使用MVP架构Android应用项目

目录 MVP简介 MVP结构 MVP与MVC区别 实战演习 正文 1.MVP简介 相信大家对MVC都是比较熟悉了:M-Model-模型.V-View-视图.C-Controller-控制器,MVP作为MVC的演化版本,那么类似的MVP所对应的意义:M-Model-模型.V-View-视图.P-Presenter-表示器.从MVC和MVP两者结合来看,Controlller/Presenter在MVC/MVP中都起着逻辑控制处理的角色,起着控制各业务流程的作用.而MVP与MVC最不同的一点是M与V

ReadHub项目Kotlin版开发指南(三、MVP架构)

ReadHub项目Kotlin版转换指南(一.环境搭建) ReadHub项目Kotlin版转换指南(二.数据库和网络请求) ReadHub项目Kotlin版转换指南(三.MVP架构) Android 开发中的 MVP 架构相信大家都已经熟悉,不熟悉的请右转 Google,ReadHub 项目从 Java 转换成 Kotlin 过程中,我们需要一套新的架构方式来实现(Kotlin 项目中没有使用 dagger2). base 为 MVP 架构的基础部分,user 为其具体使用过程. base Ba

Android中关于Handler的若干思考

在之前的博文中,讲过一些和Handler有关的知识,例如: Android 多线程----AsyncTask异步任务详解 Android多线程----异步消息处理机制之Handler详解 今天再把Handler的知识回顾总结一下. 本文包括与Handler有关的以下问题: (1)Handler的作用 (2)为什么Android中要设计为只能在UI线程中去更新UI呢? (3)Handler的两个异常 (4)Handler.Looper MessageQueue之间的关系(源码角度) (5)跟线程相

MVP架构实践

一.MVP理论简介 1.为何要在android中引入MVP ??在Android项目中,Activity和Fragment占据了大部分的开发工作.而MVP设计模式可以优化Activity和Fragment的代码. ??相信很多人阅读代码的时候,都是从Activity开始的,对着一个1000+行代码的Activity,看了都觉得难受. ??使用MVP之后,Activity就能瘦身许多了,基本上只有FindView.SetListener以及Init的代码.其他的就是对Presenter的调用,还有

介绍Model-View-Presenter在Android中的应用

这篇文章是我学习MVP模式时翻译的,原文是Konstantin Mikheev所写,传送门. 因英语水平有限,翻译的很生硬,基本靠Google,请见谅.以下是译文. 这篇文章我会通过一个最简单的例子去一步步介绍MVP模式在Android中的最佳实践.同时我也会介绍一个使MVP模式在Android开发中变简单的library. 简单?怎么才能从中获益呢? 什么是MVP View层是用来显示数据和相应数据操作的.在Android中,它可能是Activity,Fragment,View或者Dialog

MVP架构在xamarin android中的简单使用

好几个月没写文章了,使用xamarin android也快接近两年,还有一个月职业生涯就到两个年了,从刚出来啥也不会了,到现在回头看这个项目,真jb操蛋(真辛苦了实施的人了,无数次吐槽怎么这么丑),怪自己太年轻了,还好是给指定行业的人使用. 重新学习思考之后,再看自己在项目中的某些实现的代码,的确不尽人意,甚至想骂自己. 项目经常改,改来该去,代码一直增加,一个fragment也没什么功能,接近1000行的代码,用region括起来,开看起来还挺整齐的,找的时候就凉了.究其原因,没有一种模式,所