Android | Tangram动态页面之路(二)介绍
本系列文章主要介绍天猫团队开源的Tangram框架的使用心得和原理,由于Tangram
底层基于vlayout,所以也会简单讲解,该系列将按以下大纲进行介绍:
- 需求背景
- Tangram和vlayout介绍
- Tangram的使用
- vlayout原理
- Tangram原理
- Tangram二次封装
本文主要对Tangram
和vlayout
的一些概念进行介绍。
vlayout
因为Tangram
底层基于vlayout
,所以需要先了解下vlayout
。
首先,在view上的性能消耗通常有以下几种:
- 布局嵌套导致多重measure/layout
可以使用ConstraintLayout
或RelativeLayout
减少布局嵌套
- view的频繁创建与销毁
列表使用RecyclerView
来复用布局
- xml转换成view解析过程产生的内存和耗时
如果列表的样式不多,使用RecyclerView
的复用机制可以避免大量的xml解析;如果样式比较多比如商品图墙等,则有必要把xml解析提前到编译期,在编译期根据注解将xml转成对应的view类,直接使用view类创建viewHolder,当然这么做会势必会增大包体积,需要克制使用
然后,vlayout
主要解决前两点,做到复杂布局下扁平和细粒度复用。
常规的RecyclerView
使用:
// 设置适配器,管理数据源和view
recyclerView.setAdapter()
// 设置LayoutManager,指定布局方式
recyclerView.setLayoutManager()
其中LayoutManager
有3种,
LinearLayoutManager extends LayoutManager //线性
GridLayoutManager extends LinearLayoutManager //网格
StaggeredGridLayoutManager extends LayoutManager //瀑布流
在面对比较复杂的布局时,如1拖3样式,
通常只能在1拖3外边套上一层layout,然后使用LinearLayoutManager
实现。为了解决这个问题,
vlayout自定义了一个VirtualLayoutManager,它继承自 LinearLayoutManager;引入了 LayoutHelper 的概念,它负责具体的布局逻辑;VirtualLayoutManager管理了一系列LayoutHelper,将具体的布局能力交给LayoutHelper来完成,每一种LayoutHelper提供一种布局方式,框架内置提供了几种常用的布局类型,包括:网格布局、线性布局、瀑布流布局、悬浮布局、吸边布局等。这样实现了混合布局的能力,并且支持扩展外部,注册新的LayoutHelper,实现特殊的布局方式。 引用自苹果核 - Tangram 的基础 —— vlayout(Android)
大致意思是这样,
在vlayout
Demo中,使用代码是这样,
//VLayoutActivity.java
//子适配器集合
List<DelegateAdapter.Adapter> adapters = new LinkedList<>();
//创建子适配器,需指定其布局方式
SubAdapter subAdapter1 = new SubAdapter(new LinearLayoutHelper());
adapters.add(subAdapter1);
SubAdapter subAdapter2 = new SubAdapter(new ColumnLayoutHelper());
adapters.add(subAdapter2);
//把子适配器集合设置给代理适配器
delegateAdapter.setAdapters(adapters);
recyclerView.setAdapter(delegateAdapter);
可以看到,随着布局样式越来越多,代码量也会越来越多,于是,用json模板描述页面
的Tangram
诞生了。
Tangram
把vlayout
直接给到业务方使用,这样的接入成本是不能接受的,于是需要屏蔽掉vlayout
细节,让业务方用的更舒服。至于为何要引入json模板
,需求背景里已经做过介绍。
Tangram
的意思是七巧板,旨在用七巧板的方式拼凑出各式各样的页面。他抽象了两个概念,Card
和Cell
,Card
用于描述布局方式,Cell
用于描述在这个布局方式下,用什么样的view去展示,比如Tangram
Demo里的data.json
,
[
{
"type": "container-oneColumn", //Card,布局方式
"items": [
{
"imgUrl": "https://gw.alicdn.com/tfs/TB1vqF.PpXXXXaRaXXXXXXXXXXX-110-72.png",
"arrowImgUrl": "https://gw.alicdn.com/tfs/TB1vqF.PpXXXXaRaXXXXXXXXXXX-110-72.png",
"title": "标题1",
"type": "vvtest" //Cell,具体展示的view
},
{
"imgUrl": "https://gw.alicdn.com/tfs/TB1vqF.PpXXXXaRaXXXXXXXXXXX-110-72.png",
"arrowImgUrl": "https://gw.alicdn.com/tfs/TB1vqF.PpXXXXaRaXXXXXXXXXXX-110-72.png",
"title": "标题2",
"type": "vvtest"
}
]
}
]
这些布局方式Card
,在Tangram
内部会进行注册,
//TangramBuilder.java
void installDefaultRegistry(final DefaultResolverRegistry registry) {
// built-in cards
registry.registerCard(TYPE_CONTAINER_BANNER, BannerCard.class);
registry.registerCard(TYPE_SINGLE_COLUMN_COMPACT, SingleColumnCard.class);
//...
}
布局方式确定好后,需要具体的View来展示,也就是Cell
,比如单图SingleImageView
,纯文本RatioTextView
等等,这些Cell
则需手动注册,如果是偏业务的Cell
,可以在业务层按需注册,如果是更抽象的通用Cell
,则应该下沉到基础库里全局注册,更抽象的Cell
意味着需要提供更为通用的配置属性,能提供给更多不同的业务方使用。Cell
的手动注册如下,
//TangramActivity.java
void onCreate(Bundle savedInstanceState) {
//Step 3: register business cells and cards
builder.registerCell(1, TestView.class);
builder.registerCell(2, SimpleImgView.class);
//绑定recyclerView
engine.bindView(recyclerView);
JSONArray data = new JSONArray(new String(getAssertsFile(this, "data.json")));
//设置json数据
engine.setData(data);
}
Card
和Cell
都注册好了,通过TangramEngine
将数据设置进去,跟进去可以看到,Tangram
把布局能力交给了vlayout
,
//GroupBasicAdapter extends VirtualLayoutAdapter
void setData(List<L> cards, boolean silence) {
//把Card转成LayoutHelper
setLayoutHelpers(transformCards(cards, mData, mCards));
}
Tangram
把json模板中描述的一个个Card
解析成了所对应的vlayout
的布局方式LayoutHelper
,
值得注意的是,Tangram
Demo里的json模板都是包含了业务数据的,这么做可能是为了剔除掉网络请求的代码,方便开源学习,而在实际业务中不太可能把数据绑定在模板里,这样模板会很臃肿,我们要做的是,用模板描述页面结构和数据源
,而非数据本身,如,
{
"template":[
{
"card": "container-banner", //轮播图模块,使用banner布局方式
"cell":"imageView", //具体的view就是一张图片
"data":"makeup:banner" //数据来源于聚合接口,key为banner
},
{
"card": "container-fiveColumn", //类目模块,使用Column布局方式
"cell":"imageAndTextView", //具体的view是上图下文本
"data":"makeup:category" //数据来源于聚合接口,key为category
},
{
"card": "container-waterfall", //商品流模块,使用Staggered布局方式
"cell":"goodsView", //具体的view是商品样式
"data":"request:recommend" //数据来源于request,key为recommend
}
]
}
既然json模板可以由后端下发,也就意味着,我们可以让运营同学通过后台拖动模块搭建页面,选择资源位设置数据源,然后生成json模板下发,开发同学从此就可以解放双手,做更有趣(更有挑战)的事情了。
不过这都是后话了,对Tangram
和vlayout
的介绍就到这里了,下篇文章将对Tangram的使用进行更详细的讲解,点关注,不迷路~
参考文章
- 苹果核 - Tangram 的基础 —— vlayout(Android)
- 苹果核 - 页面动态化的基础 —— Tangram
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Keras中 ImageDataGenerator函数的参数用法
- CI框架网页缓存简单用法分析
- 掌握PHP垃圾回收机制详解
- PHP基于面向对象封装的分页类示例
- PHP获取对象属性的三种方法实例分析
- PHP7内核之Reference详解
- PHP基于PDO扩展操作mysql数据库示例
- php实现的PDO异常处理操作分析
- PHP yield关键字功能与用法分析
- php PDO属性设置与操作方法分析
- PHP时间日期增减操作示例【date strtotime实现加一天、加一月等操作】
- CI框架实现创建自定义类库的方法
- php如何计算两坐标点之间的距离
- Python调用C语言程序方法解析
- php workerman定时任务的实现代码