转载请注明出处:
android 官方mvp框架优化:lifecycle-mvp,像前端那样组合式写页面
地址:http://blog.youkuaiyun.com/qq_22744433/article/details/78013915
目录
1 前言
虽然在标题上,自己很随意的起了这么一个名字。其实并不是说它起个英文名就牛逼了。说白了,它其实就是mvp的思想加了lifecycle-component,然后加入了分层的思想,最后用TypeFactory取代presenter。为什么要这么改呢?因为用mvp框架时确实存在了一些问题,这些小修小改都是基于业务的基础上。目的就是:在这种框架下,别人用起来你写的组件更方便,沟通成本更低,移植性也更好。每个人对mvp的理解不一样,给大家提供一种思路~
2 mvp框架含义
之前写过一篇文章介绍了一下google官方提倡的mvp框架:。为什么官方要推荐这个呢?因为虽然mvp框架定义很简单:m代表model,提供数据;v即view,提供的是供presenter调用的view相关的方法;p 即presenter,提供的是页面里触发动作的逻辑方法。那么实施起来呢?并不是那么统一,因为自由度很大。用什么来做view?presenter的调用者都是谁?他们怎么关联?他们和activity又有什么关系?所以一时之间,网上有很多自创的mvp框架。
3 谷歌官方推荐的mvp框架
于是在众说纷纭之中,官方推荐了一个mvp的版本,具体详情的可看上面的那个链接。大体说下:
- 用contract来承载view和presenter的接口定义。这一点不是重点,设计接口规范很好。但是没有也没有关系,我认为有时候还会有过度设计之嫌,因为view和presenter都是和业务相关的,a业务场景硬要用b业务的view或presenter,肯定会有不合适之处(难道要用if…else)。即便现在合适,你挡不住pm给你加场景。
- 用fragment来实现view接口。为什么要用fragment来实现view接口呢?因为fragment有生命周期。有生命周期怎么了?这个就要从presenter的使用说起了,我们知道presenter是页面里触发动作的逻辑方法。触发动作比如页面初始化加载,加载下一页,下拉刷新,编辑,提交,删除等。这些的方法执行逻辑我们都写在presenter里,这也是mvp区分视图逻辑和业务逻辑的核心。那么presenter的在哪里调用呢?两大类:一:页面的生命周期onStart()调用presenter页面初始化加载的方法。二:页面view的监听回调onXxxListener()方法里面调用presenter的刷新,编辑,提交等方法。所以fragment做为view层的实现类的好处就体现出来了:既有生命周期方法,又有view的监听回调onXxxListener()方法,可以满足对应的presenter的调用。
- presenter处理页面里触发动作的逻辑。在fragment使用。
- 在activty层关联fragment和presenter,传入参数,在setContentView()塞进去对应的view。
ok,基本说完了,以上几点大体就是google官方推荐的mvp框架。
4 谷歌官方mvp框架的无奈
4.1 官方mvp的缺点
为什么说它无奈呢?前面说了,对于view层的接口,使用fragment来进行实现,因为fragment有生命周期。所以正是因为fragment有生命周期才使用的fragment作为view层。但fragment太笨重了。试想一下,我有一个页面,里面有四五块内容。为了以后的各块内容的移动、去除、移植更方面,我希望每一块内容都做成mvp形式,块与块之间不耦合。那么官方的这个mvp框架就不适用了。因为你不可能在一个页面写5个fragment把。android的activity中不建议写那么多的fragment,fragment典型的使用场景是ViewPager。
4.2 常规变通
那么变通一下,5块内容的view层,不再用fragment实现,而只是一个个普通的view,每个view监听事件的响应还是在view中进行(调用各自的presenter方法)。而对于整个页面的初始化加载或者下拉刷新加载,这5块内容共用一个fragment,在这个fragment的onStart()和下拉刷新的监听回调中加载5块内容对应的presenter的方法。然后在fragment的onCreateView()中把5块内容的view填充进来。5块内容之间可能还需要通信,数据交流,这些借助presenter在fragment中进行。
5 带生命周期的mvp:lifecycle-mvp
上面那么做完全没有问题,并且上面那种做法也存在于我们的项目中。但通过几个版本的迭代,我发现了一些问题:presenter太乱,太散。fragment需要持有所有的presenter,在onStart()时load()数据。各自的view也需要持有各自的presenter。并且view和presenter之间需要互相set()。你还需要在activty或者fragment的onDetroy()方法中管理presenter。总体让人觉得很乱。尤其是如果你的组件需要被别人使用,或组件用需要用到其他app时,其他人拿到你的组件,你要关心两个东西view和presenter,他得知道这两个东西里面的方法,并且他需要在activty/fragment的生命周期中关联他们并调用一些方法。嗯。这个过程肯定存在的大量沟通成本~
5.1 build方式
我认为一个好的组件,应该是这样的:这个组件提供了一系列的build方法,你只需要
View component = new Component.Builder()
.setXxx()
.setXxx()
.setXxx()
.build();
这样这个组件就构建成功了。并且这个组件是一个view,你可以把它用在任何的地方,不局限是activty或fragment。你可以把它放到更大的一个viewGroup中,然后直接把这个viewGroup放到act