天猫精灵没有语音提示(天猫精灵支持哪些电视)
前言淘宝、天猫一直致力于解决 页面动态化的问题在2017年的4月发布了v1.0解决方案:Tangram模型 及其对应的 Android库 vlayout,该解决方案在手机淘宝、天猫 Android版 内广泛使用若还不了解Tangram模型 和 vlayout,具体请看文章 1. Android Tangram模型:连淘宝、天猫都在用的UI框架模型你一定要懂 2. Android开源库V - Lay
前言淘宝、天猫一直致力于解决 页面动态化的问题在2017年的4月发布了v1.0解决方案:Tangram模型 及其对应的 Android库 vlayout,该解决方案在手机淘宝、天猫 Android版 内广泛使用若还不了解Tangram模型 和 vlayout,具体请看文章 1. Android Tangram模型:连淘宝、天猫都在用的UI框架模型你一定要懂 2. Android开源库V - Layout:淘宝、天猫都在用的UI框架,赶紧用起来吧!
淘宝、天猫一直致力于解决 页面动态化的问题 在2017年的4月发布了 若还不了解 1. Android Tangram模型:连淘宝、天猫都在用的UI框架模型你一定要懂 2. Android开源库V - Layout:淘宝、天猫都在用的UI框架,赶紧用起来吧! 在同年的12月,阿里团队对此作了重大更新:发布了 今天,我将带大家全面了解 Virtualview的Github地址 目录 1. 为什么要向 Tangram模型 加入 VirtualView 即 为什么要更新 结论 提升组件动态性,实现动态更新 提升了组件的渲染性能 具体描述 而上述解决方案的承载方案,则是 VirtualView的Github地址 2. VirtualView介绍 简介 特点 3. 实现原理 3.1 核心思路 根据 3.2 实现方案 根据其原理, 虚拟化开发的本质: 之所以称为虚拟化,是因为 3.3 总结 从上可知, 1. 通过 2. 通过 虚拟化技术(本质 = 4. 工作流程 在了解了 下面,我将开始讲解 4.1 流程概述 根据上述方案, 具体如下 4.2 流程详细分析 下面我将对每个流程的原理 & 过程详细分析 流程1:创建UI组件 具体描述 根据业务需求,创建所需要的 有2种创建方式:使用框架内置(封装好)的 1.1 使用框架内置(封装好)的 即 可直接使用封装好的 具体如下(含组件基础属性) 注: a. 自定义组件应继承基础组件 b. 系统封装 1.2 自定义UI组件 若框架内置的 自定义流程 即 上述则是虚拟化创建组件的过程 具体过程 实现基础组件需遵循一个接口的规范:定义了渲染过程中所需的3个流程:测量尺寸阶段、布局阶段 & 绘制阶段 a. 定义这3个阶段是为了符合 (2)自定义View Measure过程 - 最易懂的自定义View原理系列 (3)自定义View Layout过程 - 最易懂的自定义View原理系列 (4)自定义View Draw过程- 最易懂的自定义View原理系列 b. 在 这3个过程具体如下:(与 不论是虚拟 / 原生组件,都采用上述模型 & 流程定义 a. 对于虚拟组件:在这些接口里实现相关逻辑 / 通过封装原生组件实现 b. 对于原生组件:在这些接口的实现里 调用原生组件的对应逻辑 结论:可混合使用虚拟控件 & 实体控件 至此,对于宿主的布局容器来说,包装在内部的组件不分虚拟化 /原生,暴露在外的接口相同,只要将宿主容器像普通的 特别注意 此处即可解释 为何渲染性能高:因虚拟组件使用得越多, 如下所示的组件: a. 普通的原生开发:2层(宿主容器层 + 图片组件层) b. 虚拟化开发:采用虚拟化开发后,最终呈现的 View层级只有一个宿主容器(实际上,图片组件被绘制在 1.3 总结 创建 1. 直接使用框架内置的 2. 自定义组件:通过封装好的 流程2:创建界面模板 & 下发 该步骤包括多个步骤:创建 具体如下 2.1 创建XML界面模板 具体描述 根据业务需求,使用XML编写模板 注:需使用专门的工具 使用说明见文章virtualview_tools使用指南 此方式类似: 区别在于: 脱离了平台限制,即一套模板可同时在 运行时动态加载 2.2 编译成二进制数据 2.2.1 具体描述 使用专门的工具 使用说明见文章virtualview_tools使用指南 注:为什么通过 XML 编写的业务组件 不直接在客户端里运行使用,而是先进行一次二进制序列化操作? 2.2.2 二进制文件描述 借鉴了 2.2.2 编译流程 一个业务组件对应着一份 编译数据 含除内置字符串资源外 它依赖的所有字符串、表达式资源 编译规则 编译时,模板里涉及的资源包括颜色值、各种枚举、基础组件的类型等都会被序列化映射成整数;不能序列化成整数的资源如字符串,就分配一个索引 原因:当模板在线发布、字符串有变动的情况下,能够不影响原来的字符串资源索引;否则若按照带有顺序约定的协议来分配资源索引,很容易在模板变更时 同一索引值在变更前后指向的资源内容是不一样,影响稳定性和动态性 序列化的规则如下: 编译流程 2.3 模板数据 下发到客户端 即 客户端获取编译后的二进制数据 获取有2种路径: 1. 直接将编译后的模板打包到客户端里,开发者通过代码加载 2. 框架先发布到模板管理后台,客户端在线更新到模板数据(即实现了动态更新) 流程3:客户端加载界面 客户端获取到编译后的界面模板后,进行加载 & 解析,最终渲染出视图界面 步骤流程如下图 3.1 解析模板数据 具体描述 客户端获得编译后的模板数据(二进制数据)后,立即 进行解析 如校验版本号,合法性,读取头信息等 客户端渲染组件 从解析 编译后的模板数据开始 流程解析 解析过程 = 二进制编译的逆过程 但解析流程只负责提取原始数据 & 组织格式,并无构建出组件对象 3.2 加载组件视图 具体描述 当用户传入一个模板名称,框架内部就会根据名称去之前解析XML界面模板的数据里找到 与此名称匹配的模板数据,然后加载 & 创建出真正的组件 流程解析 3.3 绑定业务数据 具体描述 开发者在组件属性里可通过 表达式 指定使用哪个数据字段,即将业务数据绑定到组件上 因业务数据是动态的,故从模板创建的组件不含业务数据 流程解析 在创建组件的过程中,当解析属性碰到表达式时,会将该属性的key、表达式值、所属的基础组件等关系存储起来,等真实数据到达后再通过 表达式里的定义 访问数据 & 将真实值设置给组件的属性,即将真实的数据绑定到基础组件的属性上 通过表达式解析、访问得到的属性值,会缓存起来,当原始数据引用不变时,每次访问都会获取到缓存值 此处接收的数据是 4.3 总结 5. 整体架构设计 根据上述方案 & 工作流程, 下面,我将对每部分进行详细分析 模块1:加载模块 示意图 说明 模块2:构造模块 示意图 说明 此处详细分析 基础组件模型 & 虚拟组件 a. 基础组件模型 含基础组件 & 基础属性,具体如下 注:自定义的基础组件应继承基础定义 & 扩展 模块3:辅助模块 示意图 说明 特别注意:引入用户数据绑定的表达式的原因 开发业务组件时,基础属性 / 样式不能在模板里直接写死,而是需从数据里动态获取 模块4:管理模块 示意图 说明 模块5:更新模块 示意图 说明 配套使用的工具 & 服务 示意图 说明 总结 6. 使用教程 根据上述工作流程,其使用流程同样分为3步:创建 下面,我将根据上述3个步骤进行详细解析 6.1 创建UI组件 从一文可知,创建 1. 直接使用框架内置的 2. 自定义组件:通过封装好的 此处为方便讲解,直接使用框架内置的 6.2 创建界面模板 此步骤包括:创建XML界面模板、编译成二进制数据、模板下发 6.2.1 创建XML界面模板 根据业务需求,使用XML编写模板 注:需使用专门的工具 使用说明见文章virtualview_tools使用指南 示例布局 属性数据来源: 6.2.2 编译成二进制数据 使用专门的工具 使用说明见文章virtualview_tools使用指南 6.2.3 模板下发到客户端 有2种路径: 1. 直接将编译后的模板打包到客户端里,开发者通过代码加载 2. 框架先发布到模板管理后台,客户端在线更新到模板数据(即实现了动态更新) 此处选择方式1 6.3 客户端解析 & 加载界面模板 具体使用如下 测试结果 下图展示的“超高性 99.9% 的用户觉得很快”即为 至此,关于 更加详细使用,请参考文章VirtualView的使用文档 7.VirtualView 的意义 对于个人的看法, 7.1 对于 Tangram 模型 1. 实现组件的动态性:可在端上绑定动态下发的 2. 提升了组件的渲染性能:通过 虚拟化技术(本质 = 7.2 对于整个原生开发技术(Android、iOS) 开发周期长 & 成本大 无法热更新 相比于前几年产品开发的一味求快,如今互联网行业发展暂缓、用户需求基本满足的情况下,更加 讲求的是用户体验 所以,实际上对比于 前端、 7.3 呼吁 虽然 希望大家能一起在Github - alibaba - VirtualView 上进行完善,共同为开源事业做贡献吧! 8. 总结 看完本文,你应该非常了解阿里出品的 关于 Android Tangram模型:连淘宝、天猫都在用的UI框架模型你一定要懂 Android开源库V - Layout:淘宝、天猫都在用的UI框架,赶紧用起来吧!前言
v1.0
解决方案:Tangram
模型 及其对应的 Android
库 vlayout
,该解决方案在手机淘宝、天猫 Android
版 内广泛使用Tangram
模型 和 vlayout
,具体请看文章 Tangram2.0
版本,主要是补充了Android
库VirtualView
,也广泛应用于淘宝、天猫客户端 Tangram 2.0
版本的新成员:Virtualview
Tangram2.0
版本VirtualView
Tangram v1.0
中 出现的问题:UI
组件无法动态更新 & 加载性能低,VirtualView
的具体解决方案如下VirtualView
的实现方案是:虚拟化开发Canvas
绘制的视图不存在一一对应的实体View
VirtualView
的创新在于: XML
模板实现组件的动态性 Canvas
)开发组件,提升了组件的渲染性能VirtualView
的本质原理 & 整体架构后VirtualView
的工作流程VirtualView
的工作流程分为3大部分:创建UI组件、创建界面模板 & 客户端加载界面UI
组件UI
组件 / 自定义UI
组件UI
组件而不需自身创建UI
组件的原理 同 “自定义UI
组件,下面将具体讲解UI
组件无法满足需求,则开发者可自定义UI
组件VirtualView
抽象 & 封装了 Canvas
绘制视图的流程,使得开发者只需按指定的接口协议实现1个组件的绘制逻辑:测量、绘制 & 绘制,即能实现在宿主容器通过 Canvas
直接绘制 UI
内容,从而创建虚拟化组件Android
系统的使用,即View
绘制的三大流程:measure
过程、layout
过程、draw
过程。若不了解,请看文章 iOS
平台下也需按照本方案的规范去处理Android View
绘制的三大流程相似) View
一样添加到的视图界面上,就可在后续的渲染过程中显示出来。View
个数就越少,即层级越扁平 Canvas
里了) UI
组件有2种方式: UI
组件 Canvas
流程,按照指定接口协议实现绘制逻辑 / 封装原生组件XML
界面模板、编译成二进制数据、下发等virtualview_tools
编写,其 Android
平台上通过 XML
搭建界面的方式Android
、iOS
上使用XML
模板数据,动态更新界面结构// 引用的组件通过流程1中获取 // 动态数据通过表达式从 JSON 数据里获取 <?xml version="1.0" encoding="utf-8"?> <VHLayout flag="flag_exposure|flag_clickable" orientation="H" layoutWidth="match_parent" layoutHeight="wrap_content"> <NImage id="1" src="${logoUrl}" layoutMarginLeft="8" layoutMarginRight="8" layoutMarginTop="8" layoutMarginBottom="8" layoutWidth="32" layoutHeight="32"/> <NText id="2" text="${title}" layoutGravity="v_center" gravity="${style.text-align}" textSize="${style.font-size}" textColor="${style.color}" layoutWidth="match_parent" layoutHeight="wrap_content"/></VHLayout> // JSON数据 { "style": { "text-align": "h_center", "font-size": "20", "color": "#FF5000" }, "title": "超高性 99.9% 的用户觉得很快", "logoUrl": "https://gw.alicdn.com/tfs/TB1yGIdkb_I8KJjy1XaXXbsxpXa-72-72.png" }123456789101112131415161718192021222324252627282930313233343536373839404142
virtualview_tools
将编写好的XML
界面模板编译成二进制数据,编译后的文件的后缀名是.out
Android
系统编译模板文件的思路,格式 & 描述具体如下XML
模板 = 单独编译成二进制数据Id
指向它 & 将它们单独存储到一块区域里JSON
格式VirtualView
的整体框架分为2部分:核心功能模块(5个模块) + 配套工具 & 服务。具体如下:/** * 访问数据属性的表达式 * 语法说明 * a. 以 “${” 开头、以 “}” 结束 * b. 对于Map,通过“.”操作符访问 * c. 对于 Array / List,通过 “[]” 操作符访问 * 示例如下 */ ${benefitImgUrl}; ${data[0].benefitImgUrl}; /** * 条件表达式 * 作用:根据数据中某个字段 来设置值的属性 * 语法说明 * a. 以 “@{” 开头、以 “}” 结束, * b. 中间部分 = 表达式的具体内容: 条件表达式 ? 结果表达式[1] : 结果表达式[2] * 注:1. 当条件表达式成立的时,使用结果表达式[1],否则使用结果表达式[2] * 2. 条件表达式支持布尔类型、字符串类型、JSONObject、JSONArray * c. 对于 Array / List,通过 “[]” 操作符访问 * 示例如下 */ @{${logoUrl} ? visible : invisible };12345678910111213141516171819202122232425
UI
组件、创建界面模板 & 客户端加载界面UI
组件有2种方式: UI
组件 Canvas
流程,按照指定接口协议实现绘制逻辑 / 封装原生组件UI
组件virtualview_tools
编写,其 /** * 使用说明: * 1. 控件引用:通过XML引用控件为方便讲解,XML内引用的VHLayout、NImage、NText 都是框架内置的控件:2个横向线性布局;每个布局 = 1个图 + 1个文本 * 2. 属性设置:可写死 / 通过表达式绑定一个数据字段(JSON)引用 * 布局说明: * 1. 引用的控件VHLayout、NImage、NText等都是框架内置的控件 * 2. 整个布局 = 2个横向线性布局,每个布局 = 1个图 + 1个文本 */ <?xml version="1.0" encoding="utf-8"?> <VHLayout flag="flag_exposure|flag_clickable" orientation="V" layoutWidth="match_parent" layoutHeight="wrap_content"> <VHLayout flag="flag_exposure|flag_clickable" orientation="H" layoutWidth="match_parent" layoutHeight="wrap_content"> <NImage id="1" src="${logoUrl}" layoutMarginLeft="8" layoutMarginRight="8" layoutMarginTop="8" layoutMarginBottom="8" layoutWidth="32" layoutHeight="32"/> <NText id="2" text="${title}" layoutGravity="v_center" gravity="${style.text-align}" textSize="${style.font-size}" textColor="${style.color}" layoutWidth="match_parent" layoutHeight="wrap_content"/> </VHLayout> <VHLayout flag="flag_exposure|flag_clickable" orientation="H" layoutWidth="match_parent" layoutHeight="wrap_content"> <VImage id="1" src="${logoUrl}" layoutMarginLeft="8" layoutMarginRight="8" layoutMarginTop="8" layoutMarginBottom="8" layoutWidth="32" layoutHeight="32"/> <VText id="2" text="${title}" layoutGravity="v_center" gravity="${style.text-align}" textSize="${style.font-size}" textColor="${style.color}" layoutWidth="match_parent" layoutHeight="wrap_content"/> </VHLayout> </VHLayout>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
JSON
{ "style": { "text-align": "h_center", "font-size": "20", "color": "#FF5000" }, "title": "超高性 99.9% 的用户觉得很快", "logoUrl": "https://gw.alicdn.com/tfs/TB1yGIdkb_I8KJjy1XaXXbsxpXa-72-72.png" }12345678910
virtualview_tools
将编写好的XML
界面模板编译成二进制数据,编译后的文件的后缀名是.out
// 1. 初始化图片加载器 VafContext.loadImageLoader(mContext.getApplicationContext()); // 2. 初始化 ViewManager 对象 ViewManager viewManager = vafContext.getViewManager(); viewManager.init(mContext.getApplicationContext()); // 3. 加载编译后的模板数据(二进制文件) // 方式1:直接加载二进制字节数组(推荐使用) viewManager.loadBinBufferSync(TMALLCOMPONENT1.BIN); viewManager.loadBinBufferSync(TMALLCOMPONENT2.BIN); // 方式2:通过二进制文件路径加载 viewManager.loadBinFileSync(TMALLCOMPONENT1_PATH); viewManager.loadBinFileSync(TMALLCOMPONENT2_PATH); // 4. 注册事件处理器,如常用的点击、曝光处理 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; } }); // 5. 通过组件名参数 name 生成组件实例 View container = vafContext.getContainerService().getContainer(name, true); mLinearLayout.addView(container); // 6. 为组件绑定真实的数据 // 假若您在组件模板里写了数据绑定的表达式 IContainer iContainer = (IContainer)container; JSONObject json = getJSONDataFromAsset(data); if (json != null) { iContainer.getVirtualView().setVData(json); }123456789101112131415161718192021222324252627282930313233343536373839404142434445
VirtualView
的展示效果VirtualView
的使用讲解完毕VirtualView
的补充其重大意义在于2个方面:对于 阿里Tangram
模型 & 整个原生开发技术(Android、iOS)
VirtualView
的解决的问题 在于: XML
界面模板 & 数据 Canvas
)开发组件VirtualView
的创新在于:解决了 原生开发中一直被诟病 而 常被叫喧会被 前端、RN
技术取代的问题:VirtualView
采用XML
描述视图,XML
界面模板具备跨平台使用的特性VirtualView
可在端上绑定动态下发的 XML
界面模板 & 数据,从而实现热更新RN
技术在客户端的实现,VirtualView
的优势或许会更明显:在解决了原生开发效率慢、周期长的前提下,保证了原生开发的优势:性能好VirtualView
推动了原生开发的发展,但目前来说,VirtualView
还是存在不少问题VirtualView
的使用 & 原理Tangram
的使用,建议看文章: