Android中的构架模式一直是一个很hot的topic, 近年来Architecture components推出之后, MVVM异军突起, 风头正在逐渐盖过之前的MVP.
其实我觉得MVP还是有好处的, 比如灵活多变(其实只是我用起来更熟悉顺手一些吧).
个人是没有什么偏见的, 关于项目的构架, 只要找到适合的就行.
最近打算实际用一下mosby这个开源库, 帮助构建一下mvp模式, 本文是我的心路历程和代码心得记录.
前几年MVP模式的风很大, 之前工作的项目也用的MVP模式, 所以对这个模式在team有很多讨论.
可以说一千个人眼中有一千种MVP吧, 比如Presenter之后的数据逻辑, 是用Interactor呢, 还是用Repository呢, 如果用了CursorLoader, 那么数据和View层直接耦合怎么办. 要不要给Presenter也定义接口呢, Presenter是注入呢还是在哪里(比如基类Fragment里)初始化呢, P和V的attach到底是在P里做呢还是在V里做呢.
MVP的原则尽管结合项目实际, 可能有很多变种, 但是不管怎么变, MVP有几个原则是要遵守的:
Activity/Fragment实现View接口, View中的方法都只是和UI显示相关的. View要尽可能的dummy, 不涉及业务逻辑, presenter告诉它干什么它干什么就行了.
Presenter中没有Android相关的类, 是一个纯Java的程序. 这样有利于解耦和测试. (所以一个检查方法是看你的presenter的import中有没有android的包名.)
注意生命周期的处理, 因为异步任务callback返回之后View的状态不一定还是活跃的, 所以要有一定的措施检查View是否还在以及处理注销等, 避免crash或内存泄露.
MVP的官方例子MVP模式Google有个官方例子: android-architecture, 我之前写了一篇解读在这里Google官方MVP Sample代码解读. (我刚看了一下官方sample代码又更新了, 还得再看一下.)
官方的例子属于比较正统的, 比如每个界面会定义一个Contract, 里面分别定义View和Presenter的接口. 用Repository包装local和remote的数据, local和remote的数据源会和repository实现相同的data source接口, 我非常喜欢RxJava版本的三级缓存处理.
我的一些小Demo之前自己写的一些比较完整的使用MVP的Demo:
TodoRealm: 一个Todo任务管理器, 只有本地数据.
ZhihuDaily: 知乎日报, 支持离线模式.
MVVM自从Google官方推出了Android Architecture Components之后, 看起来MVVM也是一种不错的选择.
这是官方的例子: android-architecture-components.
我还正在学习中, 关于这个话题可能以后会单独展开来讲一下, 我先沉淀一下.
目前的心得: 这一套东西也很强大, 就是用起来不太习惯. 要遵循的套路太多, 感觉没有使用MVP的时候那么自由. (可能还是不太熟的缘故吧, 我还是不多说了. ==!)
所以在学习这套模式的时候我突然又怀念起MVP模式, 准备把之前一个烂尾的个人项目重新拯救一把. 就是这个: GithubClient. 这一次准备用个mvp的库玩玩.
Mosby库的使用和代码分析Mosby是一个帮你实现MVP或MVI的库.
最近看介绍才发现它的名字是根据How I met your mother这个美剧的主角起的. (我最近才利用生病期间看完这个剧. 觉得真是巧合啊, 注定要用一用了.)
之前都是自己手动实现MVP的, 也没什么难的, 用这个库会帮你解决什么问题呢?
看看Mosby的介绍:
Mosby Github Repo
Mosby Getting Started
Mosby MVP
使用Mosby的基本步骤:View接口继承MvpView.
Presenter: 如果有规定Presenter接口, 接口继承MvpPresenter<View>, 其中View是对应的View接口, 实现类继承MvpBasePresenter<View>.
如果没有Presenter的接口而直接是实现类也可以, 同样也是实现类继承MvpBasePresenter<View>.
Activity或Fragment实现View接口, 继承MvpActivity或MvpFragment, 泛型参数类型传入对应的View接口和Presenter类型即可.
Activity或Fragment实现抽象的createPresenter()方法, 在其中创建Presenter的实例.
好了, 所有必须的工作就做完了, mosby的类会处理初始化和实例保存等.
Activity/Fragment中不需要保存presenter的字段, Presenter中也不需要保存View的字段. 这些都在基类中保存了.
关于Mosby的实现可以查看它的类, 里面有详细的注释.
生命周期
MvpActivity中用了ActivityMvpDelegateImpl, 在Activity的每一个生命周期回调中做一些事情.
在onCreate()中创建了Presenter, 把它赋值给字段, 并且attachView(); 在onDestroy()中detachView()和调用presenter的destroy()来做一些清理工作.
MvpFragment中用了FragmentMvpDelegateImpl, 在Fragment的生命周期中做一些事情: 在onCreate()中创建Presenter, 赋值给字段; onViewCreated()中attachView(); onDestroyView()中detachView(); onDestroy()中调用presenter的destroy()来做一些清理工作.
所以presenter的初始化, 和view的attach/detach, 以及它们变量的保存都是mosby帮我们处理好了.