写点什么

Android | Tangram 动态页面之路(二)介绍

用户头像
哈利迪
关注
发布于: 2020 年 05 月 17 日
Android | Tangram动态页面之路(二)介绍

本系列文章主要介绍天猫团队开源的Tangram框架的使用心得和原理,由于Tangram底层基于vlayout,所以也会简单讲解,该系列将按以下大纲进行介绍:


  1. 需求背景


  1. Tangram 和 vlayout 介绍


  1. Tangram 的使用


  1. vlayout 原理


  1. Tangram 原理


  1. Tangram 二次封装


本文主要对Tangramvlayout的一些概念进行介绍。


vlayout


因为Tangram底层基于vlayout,所以需要先了解下vlayout


首先,在 view 上的性能消耗通常有以下几种:


  • 布局嵌套导致多重 measure/layout


可以使用ConstraintLayoutRelativeLayout减少布局嵌套


  • view 的频繁创建与销毁


列表使用RecyclerView来复用布局


  • xml 转换成 view 解析过程产生的内存和耗时


如果列表的样式不多,使用RecyclerView的复用机制可以避免大量的 xml 解析;如果样式比较多比如商品图墙等,则有必要把 xml 解析提前到编译期,在编译期根据注解将 xml 转成对应的 view 类,直接使用 view 类创建 viewHolder,当然这么做会势必会增大包体积,需要克制使用


然后,vlayout主要解决前两点,做到复杂布局下扁平和细粒度复用。


常规的RecyclerView使用:


// 设置适配器,管理数据源和viewrecyclerView.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)


大致意思是这样,



vlayoutDemo 中,使用代码是这样,


//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的意思是七巧板,旨在用七巧板的方式拼凑出各式各样的页面。他抽象了两个概念,CardCellCard用于描述布局方式,Cell用于描述在这个布局方式下,用什么样的 view 去展示,比如TangramDemo 里的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.javavoid 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.javavoid 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);}
复制代码


CardCell都注册好了,通过TangramEngine将数据设置进去,跟进去可以看到,Tangram把布局能力交给了vlayout


//GroupBasicAdapter extends VirtualLayoutAdaptervoid setData(List<L> cards, boolean silence) {    //把Card转成LayoutHelper    setLayoutHelpers(transformCards(cards, mData, mCards));}
复制代码


Tangram把 json 模板中描述的一个个Card解析成了所对应的vlayout的布局方式LayoutHelper



值得注意的是,TangramDemo 里的 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 模板下发,开发同学从此就可以解放双手,做更有趣(更有挑战)的事情了。


不过这都是后话了,对Tangramvlayout的介绍就到这里了,下篇文章将对 Tangram 的使用进行更详细的讲解,点关注,不迷路~


参考文章




发布于: 2020 年 05 月 17 日阅读数: 724
用户头像

哈利迪

关注

. 2019.02.13 加入

公众号:哈利迪ei

评论 (2 条评论)

发布
用户头像
非常感谢分享移动开发技术,期待更多好内容。这篇文章InfoQ官网推荐啦。
2020 年 05 月 17 日 12:03
回复
感谢~
2020 年 05 月 18 日 19:52
回复
没有更多了
Android | Tangram动态页面之路(二)介绍