带你学习阿里巴巴的开源库VLayout
14日,京东在总部召开“京东游戏泛娱乐产业联盟发布会”,宣布完成对原LPL(英雄联盟职业联赛)队伍QG战队及LSPL(英雄联盟甲级联赛)队伍NON两支战队的收购。同时公布了“三步曲战略”,持续向泛娱乐生态发力:第一步深化与游戏IP的合作,第二步全力打造顶尖电竞战队,第三步开展影视、动漫、体育等更多泛娱乐领域的合作,全面开启围绕粉丝的泛娱乐时代。
作者简介今天星期五呀,明天不上班,提前祝大家周末愉快!
本篇来自 Carson_Ho 的投稿,详细的分析了一款阿里开源的强大UI框架,希望能够帮助到大家!
温馨提示:由于成熟的框架流程复杂,文中部分流程图很大,用手机的朋友可以点击图片,放大后查看!
Carson_Ho 的博客地址:
http://blog.****.net/carson_ho
前言
V- Layout 是阿里出品的基础 UI 框架,用于快速实现页面的复杂布局,在手机天猫 Android版 内广泛使用。
让人激动的是,V- Layout 终于在 Github 上开源:
https://github.com/alibaba/vlayout
我对 V- Layout 进行了详细分析,我将献上一份 V- Layout 的使用攻略 & 源码分析,希望你们会喜欢。
为什么要使用V-Layout
在讲解 `V - Layout` 前,我们先来搞懂一个问题:为什么要使用 `V - Layout`
背景
Android中 UI 性能消耗主要来自于两个方面:
布局层次嵌套导致多重 measure/layout
View 控件的创建和销毁
为了解决上述问题,现有的解决方式是:
少用嵌套布局
使用 ListView/GirdView/RecyclerView 等基础空间来处理 View 的回收与复用。
但是,很多时候我们需要在一个长列表下做多种类型的布局来分配各种元素,,特别是电商平台首页等页面,布局元素结构更加复杂多样。如下图:
此时的解决方案有所变化:不采用子View的复用,只采用一个主要的复用容器(如ListView 或 RecyclerView+LinearLayoutManager),然后在其中使用嵌套方式直接用各个组件进行拼接,减少了复用的能力
问题
这种做法还是会损失android应用的性能。
解决方案
通过自定义 LayoutManager 管理所有的布局类型
即阿里出品的基础 UI 框架项目 VirtualLayout就是采用该方式来解决上述问题
简介
定义:VirtualLayout 是阿里出品的基础 UI 框架项目
作用:快速实现复杂的布局格式的混排
基于 RecyclerView & LayoutManager 扩展
原理分析
V - Layout 的本质原理是:通过自定义一个 VirtualLayoutManager(继承自 LayoutManager),用于管理一系列 LayoutHelper,将具体的布局能力交给 LayoutHelper 来完成,从而 快速实现组合布局 的需求。
每个 LayoutHelper 负责页面某一个范围内的布局
V - Layout 默认实现了10种默认布局:(对应同名的LayoutHelper)
源码类说明
V - Layout的源码类图如下:
1. RecyclerView
定义:页面布局的主体
特别注意:在V - layout框架里绑定 VirtualLayoutAdapter(继承Adapter) & VirtualLayoutManager(继承LayoutManager)
2. VirtualLayoutAdapter
定义:数据适配器。继承自系统的Adaper
作用:创建组件 & 绑定数据到组件
额外:定义了两个接口:
getLayoutHelper():用于返回某个位置组件对应的一个 LayoutHelper
setLayoutHelpers():调用此方法设置整个页面所需要的一系列 LayoutHelper
这两方法的具体实现委托给 VirtualLayoutManager 完成
3. VirtualLayoutManager
定义:布局管理器。继承自系统的 LinearLayoutManager
作用:
在 RecyclerView 加载组件或者滑动时调用 VirtualLayoutManager 的 layoutChunk(),返回当前还有哪些空白区域可摆放组件
管理 LayoutHelper 列表
额外:实现了 VirtualLayoutAdapter 的 getLayoutHelper() & setLayoutHelpers()
4. LayoutHelperFinder
定义:LayoutHelper 寻找器
作用:根据页面状态 寻找对应的 LayoutHelper 并返回给 VirtualLayoutManager
VirtualLayoutManager 会持有一个 LayoutHelperFinder
当 layoutChunck() 被调用时会传入一个位置参数,告诉 VirtualLayoutManager 当前要布局第几个组件
VirtualLayoutManager 通知持有的 LayoutHelperFinder 找到传入参数位置对应的 LayoutHelper(每个 LayoutHelper 都会绑定它负责的布局区域的起始位置和结束位置)
5. LayoutHelper
定义:布局协助器
作用:负责具体的布局逻辑
其中定义了一系列接口用于和 VirtualLayoutManager 通信:
6. MarginLayoutHelper
定义:继承自 LayoutHelper
作用:扩展 LayoutHelper,提供了布局常用的 内边距padding、外边距margin 的计算功能
7. BaseLayoutHelper
定义:MarginLayoutHelper 的第一层具体实现
作用:填充 当前LayoutHelper 在屏幕范围内的具体区域 背景色、背景图等逻辑
8. 子LayoutHelper
定义:MarginLayoutHelper 的第二层具体实现
作用:负责具体的布局逻辑
每种 子LayoutHelper 负责一种布局逻辑
重点实现了 beforeLayout()、doLayout()、afterLayout()
特别是 doLayout():会获取一组件,并对组件进行尺寸计算、界面布局
V - Layout 默认实现了10种默认布局:(对应同名的LayoutHelper)
特别注意:
每一种 LayoutHelper 负责布局一批组件范围内的组件,不同组件范围内的组件之间,如果类型相同,可以在滑动过程中回收复用。因此回收粒度比较细,且可以跨布局类型复用.
支持扩展外部:即注册新的 LayoutHelper,实现特殊的布局方式。下面会详细说明
工作流程
V - Layout 的工作流程分为 初始化 & 布局流程。如下图:
初始化
在使用 V - layout 快速实现复杂布局前,需要先做一系列的初始化工作。
初始化流程与使用普通的 RecyclerView + LayoutManager 初始化流程基本一致:Vlayout的使用者
此处的初始化 实际上就是使用者在使用 V - layout 时需要做的初始化工作。
具体布局流程
当完成初始化工作后,每当用户刚打开页面第一次渲染布局 或 用户滑动页面时,都会进行一次布局流程
布局流程的本质是:自定义 VirtualLayoutManager 持续获取页面状态,并通过LayoutHelperFinder 找到对应的 LayoutHelper 从而实现对应的布局逻辑,从而快速实现组合布局的需求。具体流程如下:
下面用一张图总结 V - Layout 的原理 & 工作流程
使用步骤
V - Layout 的使用其实就是上面说的初始化工作。使用步骤如下:
步骤1:创建RecyclerView & VirtualLayoutManager 对象并进行绑定
步骤2:设置回收复用池大小
如果一屏内相同类型的 View 个数比较多,需要设置一个合适的大小,防止来回滚动时重新创建 View)
步骤3:设置Adapter
设置 V - Layout的Adapter有两种方式:
方式1:继承 自 DelegateAdapter
方式2:继承 自 VirtualLayoutAdapter
下面会进行详细说明.
方式1:继承 自 DelegateAdapter
定义:DelegateAdapter 是 V - Layout 专门为管理 LayoutHelper 定制的 Adapter
继承自 VirtualLayoutAdapter
作用:通过管理不同布局的 Adapter,继而管理不同的 LayoutHelper,从而实现使用不同组合布局
特别注意:虽不可直接绑定 LayoutHelper,但是它内部有一个继承自 RecyclerView.Adapter 的内部类 Adapter 可以绑定 LayoutHelper;
即通过一个 List 把绑定好的 Adapter 打包起来,再放去 DelegateAdapter,这样就可以实现组合使用不同的布局
具体做法:写法与复写系统自带的 Adapter 非常类似:只比系统自带的 RecyclerAdapter 需要多重载 onCreateLayoutHelper 方法,其余类似
方式2:继承自 VirtualLayoutAdapter
定义:当需要实现复杂需求时, 可以通过继承 VirtualLayoutAdapter 从而实现自定义 Adapter。具体使用:
步骤4:根据数据列表,创建对应的LayoutHelper
1. 线性布局(LinearLayoutHelper)
布局说明:布局子元素(Item)以线性排布的布局
2. 网格布局(GridLayout)
布局说明:布局里的 Item 以网格的形式进行排列
3. 固定布局(FixLayoutHelper)
布局说明:布局里的Item 固定位置。固定在屏幕某个位置,且不可拖拽 & 不随页面滚动而滚动。如下图:(左上角)
4. 可选显示的固定布局(ScrollFixLayoutHelper)
布局说明:布局里的Item 固定位置
固定在屏幕某个位置,且不可拖拽 & 不随页面滚动而滚动(继承自固定布局(FixLayoutHelper))
唯一不同的是,可以自由设置该Item什么时候显示(到顶部显示 / 到底部显示),可如下图:(左上角)
需求场景:到页面底部显示”一键到顶部“的按钮功能
以下示意图为:滑动到底部,布局才在左上角显示
5. 浮动布局(FloatLayoutHelper)
布局说明:布局里的Item只有一个
可随意拖动,但最终会被吸边到两侧
不随页面滚动而移动
6. 栏格布局(ColumnLayoutHelper)
布局说明:该布局只设有一栏(该栏设置多个Item)。可理解为只有一行的线性布局
7. 通栏布局(SingleLayoutHelper)
布局说明:布局只有一栏,该栏只有一个Item
8. 一拖N布局 (OnePlusNLayoutHelper)
布局说明:将布局分为不同比例,最多是1拖4。具体如下图
9. 吸边布局(StickyLayoutHelper)
布局说明:布局只有一个Item,显示逻辑如下:
当它包含的组件处于屏幕可见范围内时,像正常的组件一样随页面滚动而滚动
当组件将要被滑出屏幕返回的时候,可以吸到屏幕的顶部或者底部,实现一种吸住的效果
示意图(吸在顶部)
10. 瀑布流布局(StaggeredGridLayoutHelper)
布局说明:以网格的形式进行布局。与网格布局类似,区别在于:
网格布局每栏的Item高度是相等的;
瀑布流布局每栏的Item高度是可以不相等的。
由于这篇干货篇幅较长,我上面至贴出了示例图,详细的使用方式以及实战Demo,大家可以点击最后 阅读原文 查看。
更多每天学习累了,看些搞笑的段子放松一下吧。关注最具娱乐精神的公众号,每天都有好心情。
如果你有好的技术文章想和大家分享,欢迎向我的公众号投稿,投稿具体细节请在公众号主页点击“投稿”菜单查看。
欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号: