传统MVP用在项目中是真的方便仍是累赘?

原文地址: https://gold.xitu.io/post/58b25e588d6d810057ed3659html

前言(最后奉上福利)

自从Google在去年放出MVP官方Sample后,愈来愈多的人开始加入MVP大军,MVP可谓在16年大放异彩,我也乘势推出了个人MVP框架狂刷了一波存在感android

问题

但在使用当中我也发现了诸多弊端,致使不少初学者,在写过Sample后,就再也没在本身的项目中使用过MVPgit

MVP须要建立太多的类和接口,而且每次通讯都须要繁琐的经过接口传递信息github

这是大多数使用过MVP的朋友,最能感觉到的,最近在帮公司技术面,我也时常问应聘者,可否尝试着解决这些问题?bash

解决方案

其实我以前已经有一套解决方案,其实也不能叫解决,只能说是缓解😅架构

硬解决

所谓硬解决,即是使用比较暴力的方式😂,经过Template自动生成须要的类和接口,这样少去了频繁的复制粘贴框架

软解决

所谓软解决,那就要动动脑子,稍微优雅的解决了😀oop

  1. 对于逻辑简单的页面能够不使用Presenter,直接在ActivityFragment中处理逻辑,在Presenter中若是不须要处理数据,也能够不实用Modelpost

  2. PresenterModel均可以无限制的重用,因此MVP的划分不须要太细粒度,稍微粗粒度一点,即不须要每一个ActivityFragment都给他划分一套MVP,能够几个ActivityFragment使用同一个Presenter(使用同一个类不是同一个对象,这个Presenter含有能够共用的逻辑),也可一个ActivityFragment根据不一样的需求持有多个不一样类型的Presenter对象,Model层同理,这样灵活使用,能够在必定程度上缓解MVP类和接口较多的缺点学习

并无彻底解决问题

经过上面的解决方案,是能够必定的缓解MVP的缺点,可是并不能彻底解决上述缺点

好比想重用Presenter,Presenter就必须只含有公用的逻辑,而实际项目中公用的逻辑并非那么多,因此能减小的类和接口也是颇有限的,若是强制将不一样页面的逻辑放在同一个Prsenter中,来达到重用的目的,那么每一个Activity会被迫实现许多并不须要的方法,得不偿失

寻求解决方法

所以我看了大多数MVP框架,寻求如何完全改善这个问题,像支付宝团队使用的T-MVP框架,是经过将ActivityFragment做为Presenter,将UI操做抽到Delegate中,做为View

TheMVP优势

这样作的好处是,不只能够少写不少类,并且Presenter直接就能够和ActivityFragment的生命周期作绑定(但使用 Google 最新发布的 Android 架构组件当中的 Lifecycles 就已经能够很是简单的让任何一个类与 ActivityFragment 的生命周期作绑定, 包括 Presenter, 而且 Support Library v26.1.0 已经内嵌这个组件, 不用额外的引入这个组件),且能够随便重用View(但大多数场景都是重用Presenter,由于View层变化老是比其它层频繁)

TheMVP缺点

缺点就是不能重用Presenter,而且对于Presenter的实现有限制,必须是ActivityFragment,若是要在其余地方实现Presenter,如Adapter,Dialog就必须根据它的特性从新写对应的Presenter基类

由于Presenter基类继承了ActivityFragment,若是咱们须要经过继承使用其余ActivityFragment,那就又须要修改Presenter基类,一旦某个Activity须要继承其余不一样的Activity,那又须要从新建立一个基于此ActivityPresenter基类,致使一个ActivityFragment有多个不一样的Presenter基类

分析问题,解决问题

总结一下MVP的缺点

1.粒度很差控制,控制很差就须要写过多的类和接口
2.如要重用presenter可能会实现过多不须要的接口
3.Presenter和View经过接口通讯太繁琐,一旦View层须要的数据变化,那么对应的接口就须要更改

复制代码

想要在根本上解决以上问题,我想必须换个思路,能不能经过改变传统MVP架构来解决这些问题?

实现MVP现阶段有两种方式,各有优缺点:

一个是将ActivityFragment做为Presenter,抽象一个View层出来

一个是将ActivityFragment做为View,抽象一个Presenter层出来

我想达到重用Presenter的目的,天然选择了后者

在某一天我忽然想到了Handler,他只经过一个handleMessage方法,根据Messagewhat字段处理不一样的操做,这样向上层提供一个统一的入口,下层无论如何改变并不会影响上层,而且一样能够实现多种的操做

因而根据这个思想,我从新改造了MVP架构,让Presenter经过MessageView层通讯

如何实现

先上张图

具体作法是,VIEW层持有Presenter对象,当用户请求一个事件,则调用Presenter中的方法,并把持有View引用Message传给此方法,此方法处理完请求逻辑后将数据封装到Message中,并经过Message持有的View引用回调ViewhandleMessage方法,让View作不一样的操做,最后释放掉Message的全部引用,放入消息池

Presenter并不直接持有View,方法执行完即表示和View的关系解除

Handler的原理很像,Handler是将消息放入MessageQueue,Looper去轮循处理消息,我这里是将消息放入,Presenter的方法,并当即处理消息

总结

这样就能解决上述的缺点:

  1. 少写了不少类和接口

  2. 而且Presenter只须要经过handleMessage一个方法与View通讯,也就不用繁琐的一直添加接口方法,只须要一个Message参数,经过Message封装数据,即便View须要的数据类型发生改变,也不须要更改任何方法,因此也不会影响上层调用

  3. 随便重用Presenter,即便你一个Activity,重用10个不一样的Presenter,那也只用实现一个handleMessage方法,不须要实现View中其余用不到的方法,经过一个方法一样能作到不一样的操做(传统MVP一个页面对应一个Presenter,其实大多数Presenter只有一两个方法,这样致使存在大量代码寥寥无几的Presenter,你有想过将相近的逻辑都写到一个Presenter中,一直重用Presenter有多爽吗😁)

  4. Presenter中的方法须要Activity传递一些数据时,也能够将数据封装到Message中传给Presenter,这样即便须要的数据类型发生改变,也不须要更改方法,因此也不会影响上层调用

只有能不断的灵活重用,才能感觉到MVP的强大之处

固然不少不一样的逻辑都写在一个Presenter中,虽然能够少写不少类,可是后面的扩展性确定很差,因此这个粒度须要本身控制,可是对于外包项目简直是福音

说了这么多仍是要看看Demo,具体该怎么作吧?

Go!以为好必定要右上角Star哦!

公众号

扫码关注个人公众号 JessYan,一块儿学习进步,若是框架有更新,我也会在公众号上第一时间通知你们


Hello 我叫 JessYan,若是您喜欢个人文章,能够在如下平台关注我

-- The end

相关文章
相关标签/搜索