仅作个人记录
以前用过MVP,发现他的接口太多了,并且基类要封装很多东西,就弃用了
所有就正常开发,在一个Activity里写逻辑,尽量简化、拆分
但是项目大了以后,改动起来是真的麻烦了
所以拆分了UI和数据,纯写一个类封装View,提供刷新UI的API,以及扔接口去处理数据
但是渐渐发现操作数据的时候,UI对数据层是不透明的,需要调用UI的API,操作UI的时候倒还好,直接扔动作接口就好了
最近阅读了某项目,才发现P层不是我过去理解的转发层,而是组织层
他协调了UI的API和数据的使用的先后次序
这样才可以实现,写UI的时候真正写UI,写数据的时候专门写数据
当然仅仅一个裸MVP是不够的,需要进行大量的封装以及冗余的接口声明
封装是必要的,你需要同步生命周期及使用许多API,但是接口就最好可以用EventBus+tag取代掉,这个是我最新的思路,我觉得这样很好,我未来会在自己项目中使用上这种变种的MVP
总结一下
M 数据处理的api
V view
P 组织者
所以个人认为在P层里写数据处理是不对的
一般是在V层写UI,也有更新UI的api,写不下去了扔接口给P,P帮你到M层找数据处理api,没找到就写需要的api
再对MVP理解深一点——初始化(处理点击回调、网络回调很简单,但是如何优雅处理初始化呢?)
在一个项目中看到
在初始化一个页面的时候,Title的值需要计算得出,项目代码的做法是present.setTitleData,计算好了后,调用view.setTitleData。
我个人觉得是不太好的,我是UI,我何必关注P层具有怎样的方法呢?
我有两种想法
1.MVVM,现在我终于明白了为什么要有这个框架了。我们用了Databing,就可以免去了view.setTitleData的回调操作了。那么present.setTitleData呢?P层是组织者,所以initTitleData应该从P层的构造方法里发起,然后需要一些api的话,到M层去取,由于这里用了Databing,甚至不需要回调了。这就是我对原项目代码的优化
2.在V层,直接getTitleData,然后进行设置。这个getTitleData又谁来实现呢?其实在分析了第一种方法之后我感觉我原来的做法是错的,事件流不该从V层开始,而是应该从P层组织者层开始。我之前的做法、想法都是错的。不应该是V层碰到数据做不下去了就扔接口出来,而是P层决定是更新UI还是调用数据接口。
分析下点击按钮登录的场景
事件流从click listener开始。然后this.showloadingDialog。然后我就陷入了纠结,是该叫p.sendRequest还是p.onClickLogin呢???p.onClickLogin对于V层很友好,V层不必关注我点了这个按钮到底该做啥数据处理的操作,但是我在clickLogin后还进行了this.showloadingDialog的操作,显然接下来再用onClickLogin不能包含on click login的全部含义了;选择前者就意味着V层是知道接下来要进行网路请求的,不透明了。后来我真的是灵机一动(真的得赞叹一下我的智商,真的太高了),苦恼了一会后,我想到了,我上面的P层托管了init,是为了剥夺原来我给予V层的事件流。现在OnClickListener无疑是使得事件流重新给了V层,我也需要剥夺他!所以我在V层,btLogin.setOnClickListener(p::onClickLogin());就成功剥夺了。我在p.onClickListener方法中,执行v.showloadingdialog,然后m.sendRequest(ps:m中也是简单地封装一下,由于接口隔离原则的充分贯彻,m 中的sendRequest代码无疑是这样的:NetworkManager.sendRequest(request)。堪称完美!
总结一下:
P层剥夺V层所有事件。初始化,虽然他本不属于V层事件,但是正常人包括我之前一直认为的如此,setTitleData的那份源码里 也是这样的思维。点击事件,这个完全就是V层的事件,强行获取。还有一些事件的剥夺,暂时没碰到,想不起来。那么理所应当,V、M层都成了API库,V提供更新UI的API,M提供数据处理的API,P层中有初始化事件流,click事件流,他是组织者,可以决定何时调用V层的API去更新UI,何时调用P层的API去处理数据。从此以后开发就变得极度简单了。这才是对MVP的真正理解,只有引入事件流这个概念才能彻底拆分了数据、UI。我感觉我看到的许多的MVP、MVVM框架在项目中使用的源码,都是错误的。不久后我会用事件流MVP+EventBus打造一套光速开发模式,让开发和维护简单万倍!!!
最后再次推翻一下
在看某项目的动画监听的时候,想到能不能和click一样,也让P层实现动画监听接口的方法。这样一来突然感觉P层美名其曰组织者,可是还是把UI和数据放在一起写了,只不过都经过UI和数据的封装了。不过一想也无可避免,因为业务逻辑本身就是这样处理的,交互的顺序无可避免。
回头看一下扔接口形式的MVP,请求title那就presenter.getTitleData这个倒么什么问题,click login先showDialog再present.login,再在onLoginSuccess里dismissDialog以及更新其他的UI。这里有个问题,是扔个onLoginSuccess的接口给P,还是等P的onLoginSuccess方法里调用V的更新UI的逻辑。我觉得onLoginSuccess方法由p层控制绝对是不好的,因为事件流从V层转换到了P层,应该在V层声明一个onLoginSuccess方法,在网络请求成功后,p.onLoginSuccess立刻调用v.onLoginSuccess把事件流直接托管给V层,然后onLoginSuccess后肯定还有一些业务逻辑,再由v扔接口出来就行了。
总而言之事件流在V层和事件流在P层,这两者我犹豫不决,可能还需要实战中去比较。
最近看了鸿洋的MVP文章,又多领悟了一点
P是专门为你处理复杂逻辑的,一万行的复杂逻辑,就V层就是一个接口,V层可以通过一句话就可以实现所有的功能,宛如上帝模式一样。M层是P层的API、工具类库,也可以认为是配合者,配合处理复杂逻辑。