23

Tangram动态化方案探索

 3 years ago
source link: https://zhuanlan.zhihu.com/p/70789273
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Tangram动态化方案探索

58同城 Android工程师

近几年跨平台动态化方案盛行,从最初的Hybrid到FaceBook出品的RN和阿里出品的Weex再到Google出品的Flutter。可以看出大厂也在不断探索更快速更高效的开放模式,毕竟技术为项目服务,项目为用户服务。只有更高效的迭代方式,才能尽可能的去提升用户体验。
我们开发的首页,详情页均可以理解为弱的跨端动态化技术,双端都支持相同的协议,根据不同的协议作出不同的UI展示和逻辑处理。而tangram实现了较强的动态化技术,及更有灵活性。可以减少发版次数。
Tangram的动态化技术并不像RN WEEX Flutter那样做到完全的动态化,Tangram更关注的是界面动态化,性能。下面我们来揭开Tangram的面纱。

布局灵活性

Tangream布局的灵活性是依赖阿里开源Vlayout实现的。通过重写Recyclerview的LayoutManger实现自定义灵活布局。首先我们需要理解Tangram模型

在Tangram框架中界面由卡片(Card) 和 组件(Item)构成。卡片负责布局组件,Tangram框架内置了很多Card样式。(Tangram2.0更新,对Tangram模型进行了重新的定义,从原来的『卡片』+『组件』升级成『布局』+『组件』,即原来的『卡片』认为是一种具有布局能力的组件,具备嵌套另一组件的能力)

目前卡片(布局)支持的样式如下:

流式(网格)布局(container-oneColumn),一拖N布局(container-onePlusN),浮动布局固定布局(container-float),吸顶布局(container-sticky),瀑布流布局(container-waterfall)等。具体可以参考内置布局支持

当产品提出想更改布局样式的时候只需更改协议的type即可,总会有一种满足他。

{
"type": "container-oneColumn", ---> 描述布局类型
"style": { ---> 描述样式
  ...
},
"header": { ---> 描述header
},
"items": [ ---> 描述组件列表
  ...
],
"footer": { ---> 描述footer
}
}

基于以上Tangram做到了布局灵活性的目的。

动态组件(VirtualView)

上面提到了卡片(布局),下面介绍一下卡片操作的对象组件。Tangram框架中将组件分为原生组件和动态组件。原生组件可以理解同我们日常开发首页item一样将编写ViewHolder然后根据type进行注册。这里重点说一下动态组件,动态组件是Tangram动态化的另一重要体现。
动态组件(VirtualView)是阿里推出的组件动态更新解决方案,解决APP native页面更新样式时,需要发版处理。适合经常做运营推广的页面。

VirtualView使用流程

可以看出VirtualView的整体框架View模板与数据分离,先下发模板布局,在下发数据进行模板填充。

模板文件编写

VirtualView框架内置了一些基础原子控件(NText,VText,NImage,NLine,VLine...)和基础容器控件(FrameLayout,GridLayout,VHLayout,NFrameLayout,NGridLayout,NVHLayout...)。我们可以使用这些提供的控件去编写我们的XML布局文件。(可以看到控件的命名规则是以N和V开始,有什么区别呢?)
布局xml编写栗子

<FrameLayout
        layoutWidth="340rp"
        layoutHeight="wrap_content"
        action="action"
        flag="flag_exposure|flag_clickable"
        background="#FFFFFF"
        autoDimDirection="X"
        autoDimX="340"
        autoDimY="240"
        >
        <NText 
         text="${title}"
         textSize="12"
         textColor="#999999"
         maxLines="1"
         layoutGravity="left|v_center"
         layoutWidth="match_parent"
         layoutHeight="wrap_content"
         gravity="left" />      
                
    <NImage
            scaleType="fit_xy"
            layoutWidth="212.5rp"
            layoutHeight="28.5rp"
            layoutMarginTop="29rp"
                        flag="flag_exposure|flag_clickable"
            layoutMarginLeft="30rp"
            layoutGravity="top|left"
            src="${imgUrl}"/>
 
</FrameLayout>
  1. 如何在布局文件中绑定数据?
    与DataBinding思想一致,通过EL表达式访问数据字段 如 ${title} ,同时数据绑定支持三元运算符如 @{${logoUrl} ? visible : invisible }
  2. 事件声明
    默认情况下组件是不触发事件的,只有在模板里显示地声明了才具备触发能力。事件声明属性字段是 flag,其值可以通过 | 组合一次性声明多个。如 flag="flag_exposure|flag_clickable"
  3. 事件处理
    上面我们提出了Tangram是面向界面的动态化,server下发的也是布局模板。所以Tangram不像RN,Weex,Fultter那样可以编写业务逻辑,Tangram的事件处理需要端去内置处理。
VafContext vafContext = tangramEngine.getService(VafContext.class);
vafContext.getEventManager().register(EventManager.TYPE_Click, new IEventProcessor() {

    @Override
    public boolean process(EventData data) {
        //handle here
        return true;
    }
});
vafContext.getEventManager().register(EventManager.TYPE_Exposure, new IEventProcessor() {

    @Override
    public boolean process(EventData data) {
        //handle here
        return true;
    }
});

协议数据填充

{
       "type":"detail"
        "imgUrl": "https://wwww.eest.com/c488d6dc6cd6263246bf1a07b6575def", 
        "title": "\u65b0\u534e\u533a\u4e1c\u65b9\u4e16\u7eaa\u57ce\u4e1c\u533a\u95e8\u5e02\u54c8\u54c8\u54c8\u54c8"
    }

编译器编译模板文件

为了提升解析效率和减少xml文件中的冗余数据,Tangram框架会将编写的xml布局文件编译为二进制文件。

实时预览工具

为了提升开发效率同样推出了实时预览工具

v2-4ba154f303b110ca02a26b87e841f0df_b.jpg

原生控件与虚拟控件

上面抛出个问题:可以看到控件的命名规则是以N和V开始,有什么区别呢?回复如下。
目前VirtualView提供的布局容器包含帧布局和线性布局,网格布局等,没有相对布局和约束布局的这些。因此当我们要实现一起布局效果的时候就需要嵌套很多次, 这样会影响渲染性能。基于以上问题VirtualView提出了原生控件与虚拟化控件。

原生控件:就是通过封装了系统原生 View 来实现的控件;(命名规则是以N开始)
虚拟化控件:使用 canvas 绘制创建的控件,它需要依托一个原生容器控件作为宿主容器,承重其最终的展示;(命名规则是以V开始)

它开创了一种虚拟化开发基础控件的技术,使用方只要按照指定协议实现一个基础控件的尺寸计算、绘制逻辑、布局逻辑,即能实现在宿主容器的 canvas 里实现直接绘制 UI 内容的,让最终渲染出来的视图结构呈现扁平化,提升组件渲染性能。同时为了解决虚拟化 View 带来的原生 View 的能力损失的问题,它支持加载和渲染原生基础控件,两者组合产生合力,既能最大限度发挥性能提升,又能满足特殊场景下的业务需求。

Tangram框架为我们内置了NText, VText, NImage, VImage等这些原生控件和虚拟控件。但是有些这些控件并不能满足我们所以的业务场景,如需要展示个性话进度条的View。这种情况如何处理呢,框架为我们提供了控件扩展的能力。
1.在编译工具配置文件配置映射关系 如 VIEW_ID_PicassoImage=1014

  1. 在客户端实现并注册
sViewManager.getViewFactory().registerBuilder(1014,new PicassoImage.Builder());

Tangram通过提升布局灵活性和使用动态组件达到了较强了动态化能力。动态组件将我们xml布局文件的编写由native端移到server端,从而做到的界面动态化的能力。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK