概述
作为一名资深的Android研发工程师,在开发展示型应用(如电商、资讯类APP)时,我们经常会遇到复杂的页面布局需求。传统的布局方式往往难以兼顾性能、灵活性和动态化需求。今天我们将深入探讨阿里巴巴开源的Tangram框架,这是一个专门用于快速实现组合布局的框架模型,在手机天猫Android & iOS版中得到了广泛应用。
一、Tangram框架概述
1.1 背景与动机
在移动端原生App开发中,最大的弱点就是不能像Web端那样即改即用,每次功能更新都需要等待下一个版本发布才能看到效果。虽然React Native等动态方案能在一定程度上解决问题,但在动态化或性能方面都不够完美。因此,阿里巴巴推出了Tangram框架,旨在解决以下核心问题:
- 快速构建复杂页面:通过组件化和布局容器的概念,简化复杂页面的构建过程
- 提升动态化能力:支持页面布局的动态化配置,无需发版即可更新界面
- 优化性能表现:通过高效的组件回收复用机制,提升页面渲染效率
1.2 核心设计理念
Tangram的核心设计理念可以概括为三点:
- 粗颗粒度组件化:将页面拆分为粗粒度的组件,每个组件承载特定的业务逻辑和UI展示
- 灵活布局容器:通过布局容器实现组件的灵活排列组合
- 多终端一致性:同一JSON描述可在iOS和Android端使用且表现一致
整体页面由卡片组成,卡片由组件组成。在Tangram中,组件模型是抽象出的最小可复用单元,承载业务逻辑和UI展示,以尽可能小的业务单元为颗粒度;而卡片模型负责逻辑,粗颗粒化,不提供布局细节描述,只声明布局方式。
二、VLayout实现原理深度解析
2.1 设计思路
VLayout是Tangram在Android端的核心组件之一,主要针对需要在长列表下做各种形态分配不同元素的电商首页等场景。传统的复用容器(ListView或RecyclerView)在面对这类需求时会出现以下问题:
- 复用性降低:不同类型布局的混排会导致复用效率下降
- 嵌套滑动处理复杂:需要处理复杂的嵌套滑动逻辑
VLayout通过提供基于RecyclerView的自定义LayoutManager,巧妙地解决了这些问题。
2.2 核心实现机制
VLayout的核心实现机制如下:
- 多Adapter串联:VLayout的Adapter串联多个继承RecyclerView.Adapter的Adapter来管理视图适配和数据,而非传统的单一Adapter模式
- LayoutHelper布局管理:具体的布局逻辑在LayoutHelper中实现,每个Adapter和LayoutHelper负责一个区域范围内的组件
- 高效回收复用:不同范围内的相同类型组件可以在滑动过程中回收复用,大大提升了性能
// VLayout核心实现示意
public void appendGroup(@Nullable List<L> cards) {
if (cards == null || cards.size() == 0)
return;
createSnapshot();
final List<LayoutHelper> helpers = new LinkedList<>(getLayoutHelpers());
// 根据组件大小进行扩容
mCards.ensureCapacity(mCards.size() + cards.size());
// add helper负责布局内的组件以及数据
helpers.addAll(transformCards(cards, mData, mCards));
setLayoutHelpers(helpers);
diffWithSnapshot();
// 刷新展示
notifyDataSetChanged();
}
三、VirtualView虚拟化技术详解
3.1 解决的局限性
在Tangram 1.0版本中,虽然实现了页面布局的动态化,但仍存在一个重要局限性:JSON中使用的卡片或组件的type,必须是在客户端已经实现好的才能使用。如果想要在原来版本中新增一个type类型的组件,这是无法做到的,只能通过升级客户端来实现。
为了解决这个问题,Tangram 2.0版本引入了虚拟化控件VirtualView。
3.2 虚拟化技术原理
VirtualView的核心思想是抽象和封装Canvas绘制视图流程,通过使用Canvas来实现UI控件的绘制。虚拟化意味着实现依赖于宿主容器而没有实际View(不同于常见的Button、TextView)。
通过XML引用绘制好的UI组件,从而创建出界面模板,客户端通过解析和加载XML界面模板最终渲染出界面。
3.3 核心优势
- 渲染性能高:通过虚拟化技术,渲染出来的视图结构呈现扁平化,减少了View层级
- 组件热更新:通过配套XML模板更新SDK,实现组件的热更新
- 跨平台一致性:一套XML模板可以同时在Android和iOS端使用
- 兼容性好:支持加载和渲染原生基础组件
- 使用便捷:内置一系列基础组件可直接使用
四、实际应用案例与最佳实践
4.1 接入方式
在Tangram中使用VirtualView时,很多步骤已经内置到Tangram的初始化里,外部只需要注册业务组件类型、加载模板数据、提供事件处理器:
// Step 1: 初始化Tangram
TangramBuilder.init(this, new IInnerImageSetter() {
@Override
public <IMAGE extends ImageView> void doLoadImageUrl(@NonNull IMAGE view,
@Nullable String url) {
Picasso.with(BannerTestActivity.this).load(url).into(view);
}
}, ImageView.class);
// Step 2: 注册内建cells和cards
builder = TangramBuilder.newInnerBuilder(this);
// Step 3: 注册业务cells和cards
builder.registerCell(1, TestView.class);
builder.registerCell(10, SimpleImgView.class);
builder.registerCell(2, SimpleImgView.class);
builder.registerCell(110,
TestViewHolderCell.class,
new ViewHolderCreator<>(R.layout.item_holder, TestViewHolder.class, TextView.class));
builder.registerCell(199, SingleImageView.class);
builder.registerVirtualView("vvtest"); // 注册虚拟组件
// Step 4: 构建引擎
engine = builder.build();
engine.setVirtualViewTemplate(VVTEST.BIN); // 加载模板数据
// 注册事件处理器
engine.getService(VafContext.class).setImageLoaderAdapter(new IImageLoaderAdapter() {
// ... 实现图片加载适配器
});
4.2 布局描述实例
基本布局描述文件是一个XML文件,并附带一个JSON数据文件,其中的相关数据来源都可以从数据JSON文件中使用表达式获取。一个XML就是一个组件,Tangram通过加载这个XML文件即可使用该XML文件所描述的组件,从而实现了动态新增组件类型的功能。
五、总结与展望
Tangram框架作为一个成熟的页面布局解决方案,在以下方面表现出色:
- 高度组件化:通过粗粒度组件化思想,大大提升了开发效率和代码复用性
- 卓越的动态化能力:VirtualView技术使得组件可以动态更新,无需发版
- 优异的性能表现:通过视图扁平化和组件复用机制,有效提升渲染效率
- 跨平台一致性:统一的JSON描述保证多端体验一致
然而,Tangram框架也有一定的学习成本,需要深入理解其组件模型和布局理念。对于简单页面可能显得过于复杂,但对于电商类复杂页面布局来说,它无疑是一个强大的利器。
在未来,随着移动端技术的不断发展,我们可以期待Tangram框架在以下方面持续演进:
- 更智能的布局算法:通过AI技术实现更智能的布局推荐和优化
- 更强的动态化能力:进一步降低动态更新的门槛,提升业务响应速度
- 更好的开发体验:提供更完善的工具链和可视化编辑器
作为Android开发者,深入掌握Tangram框架不仅能够帮助我们构建高性能、高可维护性的应用界面,更能让我们在面对复杂布局需求时游刃有余,为用户提供更优质的使用体验。
参考文章:
https://www.jianshu.com/p/f28f82cf6dbb