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

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

为什么要使用MVP模式

在传统的Android开发中,我们一般是使用MVC模式进行开发的。
传统MVC模式介绍:

  1. View: 视图层,对应xml文件
  2. Controller: 控制层,对应Activity和Fragment层,进行数据处理
  3. Model:实体层,负责获取实体数据

在Android开发中采用MVC模式的一个最大的弊端就是xml作为View层视图能力实在太弱,所以一般情况下我们都是通过Controller层来辅助处理一些视图的。这样的结果就导致Controller既作为控制层的同时又承担了View层的大部分功能,采用MVC模式往往会导致Activity和Fragment中的代码非常复杂。我们将Android中采用的MVC模式称为MV模式更加恰当。

MVP模式介绍:

  1. View: 视图层,对应xml文件与Activity/Fragment
  2. Presenter: 逻辑控制层,同时持有View和Model对象
  3. Model: 实体层,负责获取实体数据

MVP模式的流程图如下:

MVP模式图解

采用MVP模式的优势是:

  1. 把业务逻辑抽离到Presenter层中,View层专注于UI的处理。
  2. 分离视图逻辑与业务逻辑,达到解耦的目的。
  3. 提高代码的阅读性。
  4. Presenter被抽象成接口,可以根据Presenter的实现方式进行单元测试。
  5. 可拓展性强。

采用MVP模式的缺点:

  1. 项目结构会对后期的开发和维护有一定的影响。具体视APP的体量而定。
  2. 代码量会增多,如何避免编写过多功能相似的重复代码是使用MVP开发的一个重点要处理的问题。
  3. 有一定的学习成本。

综上所述,在Android上采用MVP模式的优势是:大大优化代码的维护性与拓展性的同时对代码进行深度解耦,使各个层级的分工更加明晰。

Android上MVP模式的简单应用

先来看看一个简单用mvp模式模拟登陆的demo,下面的示例代码和其它简单介绍MVP模式的代码没有太大区别。如果有了解过的同学可以直接跳过看下一章关于如何优化MVP模式的结构的文章。

下面我们来看看在Android上用MVP模式实现简单的登录逻辑的方式:

. 登陆界面

登陆界面

  1. 项目的结构:

    项目结构

从上面的代码结构图可看出,用MVP模式实现登陆模块需要创建6个文件,分别是M、V、P接口文件和接口的对应实现。其中LoginActivity就是View层的具体实现。这样的好处时Activity组件只需要负责处理UI相关逻辑就可以了,而相关的业务逻辑全部抽象到Presenter层中处理。通过这种方式能够很好的避免传统Android开发中的Activity/Fragment等UI组件既负责处理UI逻辑又处理业务逻辑的结果。

. 代码实现

说了这么多,最后我们来看看代码的实现吧。

  1. ILoginModel


    1

    2

    3


    public interface ILoginModel {

    void login(String name ,String password);

    }

  2. ILoginPresenter

    1

    2

    3

    4

    5

    6


    public interface ILoginPresenter {

    void loginToServer(String userName,String password);

    void loginSucceed();

    }

  3. ILoginView

    1

    2

    3

    4

    5

    6


    public interface ILoginView {

    void showProgress(boolean enable);

    void showLoginView();

    }

上面是登陆模块对应的MVP接口的具体设计,下面我来简单介绍一下接口中的几个方法:

  • ILoginModel.login(String name ,String password)登陆方法,通过该方法向服务器发送登陆请求。
  • ILoginPresenter. loginToServer (String name ,String password)通知Model响应登陆事件。
  • ILoginPresenter. loginSucceed()当登陆事件完成时(成功/失败),Model层要通知该方法登陆事件已完成。
  • ILoginView. showProgress(boolean enable)当Presenter层调用loginToServer (String name ,String password)方法时,要通过该方法通知View层显示加载动画。
  • ILoginView. showLoginView()登陆成功时,Presenter层会通过该方法通知View层登陆已成功。

下面我们来看看这几个接口的具体实现。

  1. LoginModel


    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23


    public class LoginModel implements ILoginModel{

    private ILoginPresenter presenter;

    private Handler mHandler = new Handler();

    public LoginModel(ILoginPresenter presenter) {

    this.presenter = presenter;

    }

    @Override

    public void login(String name ,String password) {

    mHandler.postDelayed(new Runnable() {

    @Override

    public void run() {

    Log.d("LoginModel", "run: ");

    presenter.loginSucceed();

    }

    },2000);

    }

    }

上面的Model层实现了login(String name,Stringpassword)登陆方法,该方法的具体实现逻辑是通过线程休眠2秒来模拟网络登陆的过程,登陆成功后会通过LoginPresenter的loginSucceed()方法来通知Presenter层登陆结果。实际开发中我们需要根据具体的业务逻辑来实现该过程。

  1. LoginPresenter


    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23


    public class LoginPresenter implements ILoginPresenter{

    private ILoginModel loginModel;

    private ILoginView loginView;

    public LoginPresenter(ILoginView loginView) {

    this.loginView = loginView;

    this.loginModel = new LoginModel(this);

    }

    @Override

    public void loginToServer(String userName, String password) {

    loginView.showProgress(true);

    loginModel.login(userName,password);

    }

    @Override

    public void loginSucceed() {

    loginView.showProgress(false);

    loginView.showLoginView();

    }

    }

从上面代码可以看出LoginPresenter的实现逻辑很简单,首先在构造方法中获取ILoginView对象并撞见ILoginModel对象。然后当View层调用loginToServer(String userName, String password)方法成功时,通知View层显示加载动画并调用ILoginModel层的login(String userName, String password)方法向服务器发送登陆请求。当登陆成功后(即Model层通知loginSucceed方法时)通过loginView.showProgress(false)方法通知View层隐藏加载动画,并通知View登陆成功。

  1. LoginActivity
    对于LoginActivity我们只需要关注其中的几个方法即可


    1

    2

    3

    4

    5

    6

    7


    loginBtn.setOnClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View v) {

    //模拟登陆,不需要账号密码

    loginPresenter.loginToServer("","");

    }

    });


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16


@Override

public void showProgress(boolean enable) {

if (enable){

progressBar.setVisibility(View.VISIBLE);

loginLayout.setVisibility(View.GONE);

}else {

progressBar.setVisibility(View.GONE);

loginLayout.setVisibility(View.VISIBLE);

}

}

@Override

public void showLoginView() {

Toast.makeText(LoginActivity.this,"登陆功",Toast.LENGTHSHORT).show();

finish();

}

上面时实现了ILoginView接口的两个方法。
结合上面的代码可以看出,当点击登陆按钮的监听事件时,我们不需要关注业务逻辑,只需要调用loginPresenter.loginToServer("","");方法即可,然后根据实际情况实现View层中ILoginView接口的方法即可,这样达到了UI业务与逻辑完全分离的目的。

原文地址:https://www.cnblogs.com/lyfankai/p/10341740.html

时间: 2024-11-10 16:42:41

Android架构篇--MVP模式的介绍篇的相关文章

应用程序框架实战十六:DDD分层架构之值对象(介绍篇)

前面介绍了DDD分层架构的实体,并完成了实体层超类型的开发,同时提供了验证方面的支持.本篇将介绍另一个重要的构造块——值对象,它是聚合中的主要成分. 如果说你已经在使用DDD分层架构,但你却从来没有使用过值对象,这毫不奇怪,因为多年来养成的数据建模思维已经牢牢把你禁锢,以致于你在使用面向对象方式进行开发时,还是以数据为中心. 当我们完成了基本的需求分析以后,如果说需要进行设计,那么你能想到的就是数据库表及表关系的设计,这就是数据建模.数据建模的主要依据是数据库范式设计,根据要求严格程度的递增分为

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模式简单介绍:以一个登陆流程为例

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

Android上实现MVP模式的途径

今天我想分享我在Android上实现MVP(Model-View-Presenter)模式的方法.如果你对MVP模式还不熟悉,或者不了解为什么要在Android应用中使用MVP模式,推荐你先阅读这篇维基百科文章和这篇博客. 使用Activity和Fragment作为View合适么? 目前,在很多使用了MVP模式的Android项目中,主流做法是将Activity和Fragment作为视图层来进行处理.而Presenters通常是通过继承被视图层实例化或者注入的对象来得到的.我认可这种方式可以节省

Android上的MVP模式

什么是MVP? MVP模式可以分离显示层和逻辑层,所以功能接口如何工作与功能的展示可以实现分离,MVP模式理想化地可以实现同一份逻辑代码搭配不同的显示界面.首先要澄清就是MVP不是一个结构化的模式,它只是负责显示层而已,任何时候都可以在自己的项目结构中使用MVP模式. 为什么要使用MVP? 我们知道在Android上逻辑接口和数据存取是紧耦合的,这个问题可以看看CursorAdapter这个例子,它既融合了适配器,同时也有显示的成分,而cursor很大程度上应该是数据数据存取层的. 对于一个可扩

Android开发中MVP模式浅析

目前为止,MVP的使用还没有一个标准,在此先记录一下目前学习到的一些Android中使用MVP的知识. 按传统的方式开发,经常会使Activity中混杂着UI交互,业务逻辑等流程.而MVP模式能巧妙的解决这个问题.先直接上一个小例子吧. /** * 定义一个对UI组件进行操作的接口,让Activity实现这个接口 * @author Quinn * @date 2015-5-9 */ public interface LoginView { public void showProgress();

Android开发之MVP模式的使用

前几天发现,在Android项目代码里有一个Activity类行数居然有1000多行,而600行左右都是逻辑控制,真正和页面控件处理相关的代码不多,虽然可以用#region <>...#endregion块包起来,但是整体来说,页面和逻辑处理揉得太紧密了,有时代码复用起来也不方便,于是,决定重构,找了一下,有MVP(Model-View-Presenter,Model层负责数据管理,View层负责页面控件数据展示与设置,Presenter负责逻辑处理,控制View层如何显示与展示数据,这种层次

Android之 用MVP模式 来实现webview 历史记录保存与显示

MVP在android上是常见的一种设计模式,在Launhcer,手机浏览器里面经常会看到,观摩了下其他大神写的,现在总结下,操刀起来写个demo 有什么问题的地方请提出来. 大家一起研究讨论. demo 下载地址;http://download.csdn.net/detail/xufeifandj/8267619 demo主要是 主页是一个webview,实现了 历史记录的添加,与显示.例子比较简单. 整个项目的结构如下: HistoryPresenter.java 主要是对view与mode

在Android上用MVP模式编程的实践

首先,谁是V?谁是P?(M我认为不是问题) View,应该是实现显示逻辑,在Android开发中,我们认为Fragment.Activity都可以被当做View,他们主要任务就是控制显示逻辑,这部分代码不太经常重用.View通过调用P的业务逻辑,来实现业务.业务包括同步的业务(可以在UI线程操作)和异步的任务(如网络.磁盘IO等耗时操作),并根据P的业务返回结果来响应地改变UI. 对Presenter的实现,我们用AndroidAnnotations框架的EBean实现(如果不熟悉这个框架,请G