在公司做MVP重构,公司蛮大的,App也蛮复杂(显示逻辑上,业务转移上基本是用户操作驱动,而非业务逻辑驱动),所以是个大MVP,三端都非常臃肿。自然会用拆分来解决问题,同时参照了谷歌官方的架构模型。
Model
Model是数据层,该层是面向业务数据进行拆分的。安照SOLID思路,将Model拆成两层:
- 业务Model,这些Model承载着部分数据,以及面向这些数据的原子逻辑。但是,当涉及到持久化(服务端通信)时,需要通过Repo(见后)
- ModelGroup,简单的将子Model按类型进行组合,可以看做是对于组合哪些业务Model和如何持久化(针对Gson)的一个说明。其中的存储是Class->Object的Map,对外暴露一个通过Class获取Object的接口。从Repo层拿到的数据都是ModelGroup
View
此处主要是Passive View(xml),思想仍然是拆分,但要保证重用和对Presenter绑定的稳定:
- 子View,由定制化View、layout构成,是比复杂Fragment更小的View部分,绑定到单一的Presenter上(该Presenter可以按需拆分成更小的部分)
- ViewGroup,由粘合(摆放子layout的ViewGroup)和include子layout实现。会成为Activity/Fragment的根View,承载了一个完整的页面
Presenter
Presenter尽量简化对外接口(只有生命周期,分离关注),用以粘合View-Model。该层是面向显示和业务进行拆分的。后续可以比较简单的衍化到MVVM中的ViewModel。
- 子Presenter,负责一个子layout和一个业务Model的粘合,如果该layout需要多个Model,则由多个子Presenter实现(演化成VM时,需要用clean arch或者其他方案合并Presenter)。
- PresenterGroup,可以是Presenter或者Activity/Fragment,PresenterGroup持有的是ModelGroup和ViewGroup,主要负责将ModelGroup Convert到Model,并将子Presenter绑定到对应的View上
Converter
新增层,用以将ModelGroup在绑定时转换到子Presenter所需的Model。可以极大的提高子Presenter的重用能力,而且可以保证子Presenter的SOLID。
Repo
新增层,隔离持久化/服务端逻辑,并且包装了Model层转换的工作。同时,作为传递数据的核心,方便实现全局对同一Model的KVO。
职能表
A依赖B:A知道B的存在,有B的reference、new了B的实例或调用B的自定义构造方法。
A使用B:A依赖B,且调用了B的方法或访问了B的field。
部分 | 职责 | 依赖 | 使用 | 备注 | 单测 |
---|---|---|---|---|---|
Activity | Fragment调度 | Fragment | Repo、Model | 使用Model应该只存在于使用Model增减Fragment的情况下 | 否 |
Fragment | Binding | Converter、Model、View | Presenter、Repo | Presenter仅使用生命周期方法 | 否 |
Repo | 存取传递Model | Model | Store | 是 | |
Store | 以不同方式存取Model | Model | 是 | ||
Converter | Model转换 | Model | 是 | ||
Model | 面向数据的业务逻辑 | Repo | 是 | ||
View | xml和定制widget | MVVM会使用到Presenter/ViewModel | 否 | ||
Presenter | 绑定View和Model | View、Model | 仅当输出为ViewState时可测 |