Android架构进阶(一)——MVP

Android传统MVC架构

传统的MVC架构中,Activity与Fragment几乎包含了M-V-C三个模块,这种开发模式很大程度上使得所有代码全部集中在一个类里面,经常混乱没有秩序,使得维护起来变得困难,经常在首次开发过程中出现问题都难以定位,跟别提后期维护,如果换人维护则更是要耗费大量时间和精力。

MVP架构

相对于MVC而言,MVP架构显然代码逻辑清晰很多,他将MVC中Activity与Fragment里的关于逻辑与数据获取的工作分配给了Model类,Presenter类,从而使Activity\Fragment实实在在的成为了V–只处理与页面上控件展示有关的操作。

传统MVC架构

安卓mvp架构demo mvp android 架构_获取数据

MVP架构

安卓mvp架构demo mvp android 架构_MVC_02

从上面的两个图我们可以看出,不论MVC还是MVP,M层的东西使没有什么变化的,我们都是在M层进行获取数据的操作。而V层在两种架构中就由不同的东西来担任了:

  • MVC中的V:严格意义上来讲就只是XML布局文件,或者是Java的自定义控件。
    这使得C层的代码就过分的庞大而且集中了,因为C层不仅仅要处理业务逻辑,还要处理页面展示等相关的逻辑(比如View的findViewById()操作、初始化),而且我们大多喜欢在业务逻辑中添加控件展示逻辑,这使得整个编码的逻辑异常庞大,有的页面甚至会达到一个方法几百上千行,严重增加了维护的成本。
  • MVP中的V:这里就纯纯的是一切处理试图展示逻辑的代码,通常我们把这些操作都放在Activity\Fragment中。
    这样一来我们就可以吧业务逻辑与页面展示逻辑分开来处理了,整体的逻辑线条也非常清晰,我们在P层中只做业务逻辑的处理,V层只做页面展示的逻辑,用户从V层操作进入,到P层进行业务判断,业务逻辑中调用Model层获取数据,Model层在回调P层返回成功失败,业务判断成功失败操作再回调V层,展示给用户。

使用MVP架构

这里我们用常用的语言环境,也是我们日常的需求中的一部分的话来举例子:

“这里如果用户点击按钮A 则通过调用接口B获取数据,如果获取数据成功,判断数据中C是否大于D,如果是展示View-E

  • 我们将 点击按钮A展示View-E 看成是页面展示逻辑,放到V层处理。
  • 我们将 调用接口B获取数据 看成是获取数据操作,放到M层处理
  • 我们将 获取数据成功 然后判断数据中 C是否大于D 这一些列操作看作是业务逻辑,我们可以放在P层

安卓mvp架构demo mvp android 架构_业务逻辑_03

通过一个整体流程图的展示,我们可以从中看出,用户能感知到的一切操作都是在V层,P层没有任何的干货,完全是处理V与M层之间业务的过度桥梁,M层只有数据请求,M-V-P各层分工相当明确。

MVP 架构的实例

这里我们来把一个应用场景,用MVP的结构方式做成一个实例,已便大家理解

实例需求

最简单的登录流程:

  • “用户输入用户名,密码,点击登录,校验输入是否正确,不正确弹窗提示,正确则调用登录接口,登录失败弹窗提示,登录成功则将返回的数据存储至本地”

代码设计

这是一个最简单的需求,也是我们日常最常见的需求之一,与MVC那种上来就写的编码习惯,MVP似乎多了一步设计代码的步骤

  • 使用MVP,通常我们会封装一个Contract的类用来管理M-V-C对应的接口模板,剩下的我们只要对应实现这三个接口即可。
public class LoginContract{
    
    public interface LoginView{
        void initView();
        void submitSuccess(Object returnData);
        void errorToast(String errMsg);
    }
    public interface LoginPresenter{
        void init();
        void submit(String username,String password);
        void loginSuccess(Object returnData);
        void loginFailed(String errMsg);
        
    }
    public interface LoginModel{
        void login(String username,String password);
    }
    
}

这里我就不写注释了,大家看方法名也可以看出来方法的功能,向这样的一个Contract类编写完成后,基本上我们这个业务及交互的流程基本上就已经确定了

安卓mvp架构demo mvp android 架构_MVC_04

  • 这里我们的入口是登录页面的Activity或者Fragment,我们将他们实现LoginContract.LoginView接口,然后重写方法,在页面初始化之前new一个Presenter对象,在页面登录按钮点击事件里我们调用presenter的submit()方法把用户名密码传进去。
  • 写一个Presenter实现LoginContract.LoginPresenter,重写里面方法,构造方法中把登录页面的LoginView传进去,并new 一个Model对象,使得presenter可以调用M层与V层的所有方法,起到桥梁的作用
  • 写一个Model实现LoginContract.LoginModel,重写里面方法,并在构造方法中传入Presenter

我们完成着些操作之后,只要按照上面流程图中的关键节点,调用相应的方法,我们的登录流程就结束了。

这里具体代码实现我就不写了,太过于平平无奇,大家应该都会实现。

注意

其实上面我省略了一个步骤,就是在编写Contract类之前,我们需要产品确认业务流程后,我们要有一个流程上的总结,也就是设计一套操作流程,你也可以画一个流程图,或者也可以自己构思,不做实际的产出物。

以上面的实例为例,我的流程逻辑如下

用户点击登录 -> 校验输入内容

    输入内容不合法 -> 弹框提示
    输入内容合法   -> 调用登录接口
  
    登录接口成功  -> 登录成功,获得返回数据 -> 保存登陆数据,跳转页面
    登录接口失败  -> 弹窗提示

有了这个逻辑之后,我们才能编写出Contract类,如果有流程图的话,效果会更好,不过会很费时。

总结

当你一个MVP架构的页面已经成型以后,如果需要修改业务逻辑,我们只需要针对P层的Presenter进行修改就可以,如果新增页面展示逻辑,我们就针对V层修改对应方法,添加接口或者数据源的时候,我们在M层添加方法或更新方法就OK

  • 当你的Contract类写好以后,你会发现,你在写代码之前,会花时间设计你的代码了,你会深入的去理解业务逻辑,这样就会减少很多的业务逻辑上的bug,如果发现bug可以在interface里面添加,条理清晰且不易混淆。
  • MVP架构是会多处很多类,但是相比MVC,MVP更拥抱接口化编程,我们维护的时候,或者有新同事接手你的项目的时候,只要看Contract类就会理解你的业务逻辑,从而更便于维护。