MVVM模式已经在业界得到广泛应用, 通过将VC/View中的逻辑剥离到viewModel中,专注数据处理和布局计算; 当一个view的元素相同却需要展示成不同样式时,viewModel便扮演类似HTML的CSS角色,多个viewModel对应一个view,实现了view的“代码复用”;
本文将在MVVM的基础上, 通过多个CellModel 对应一个Cell的方式, 减少了Cell的种类和重复布局代码,实现了代码UI和布局分离; 通过子线程提前计算不同方向的布局数据, 加快了转屏速度,滑动流畅性得到提升。
需求和UI设计
列表在竖屏(Portrait)时, 需要进行AB Test:
A. 需要展示单图/大图/三图/视频等多种Cell样式的文章;B. 展示成宫格样式
- 横屏(Landscape)时, 展示成一行多个的相册模式;
实现分析
采用常见“一种文章对应一个Cell”的方法, 有以下缺点:
- Cell种类太多: 文章类型有4-5种, 加上AB Test和横竖屏样式, Cell样式达到8种;
- 重复代码: 每种文章展示的元素都大同小异, 但是每个Cell都要重复定义并布局一次;
总体架构图
借鉴MVVM分离模式和Web端CSS控制布局的策略, 可以采用以下的方法:
- 只定义1~2种cell;
- 将Cell中元素的布局, 抽取到类似CSS的CellModel中.
- 横竖屏切换时, 只需要选择不同的CellModel;
总体的架构图如下:
- ViewModel负责从Loader中请求网络数据, 相应Controller的数据读取与增删改查;
- UICollectionView 会把当前文章信息传递给CellFactory, 查找当前文章对应的cell和cellModel;
- CellFactory查找时, 以文章id和当前屏幕方向组合的key, 尝试从内存里的CellModelCache读取CellModel; 没有则创建新的并写入内存;
- CellModel里计算的是Cell里各个UI元素的布局位置; Cell最终展示的样式, 由CellModel决定; 因此一个Cell可以使用不同的CellModel, 来展示不同的样式;
遇到的问题
实现后, 基本满足了需求; 但是如果多加载几屏数据后, 首次进行转屏, UI响应速度比较慢; 原因是等到旋转时再计算当前方向的CellModel, 耗时较多;
因为CellModel已经与UI脱离, 存储的只是元素的frame数据, 所以, 在Portrait方向时, 尝试在只线程计算Landscape方向的CellModel, 并缓存到CellModelCache中; 旋转时, 直接读取缓存;
1 | //计算Portrait方向CellModel并layout |