用WEB技术栈开发NATIVE应用:WEEX SDK原理详解

摘要: WEEX依旧采取传统的web开发技术栈进行开发,同时app在终端的运行体验不输native app。其同时解决了开发效率、发版速度以及用户体验三个核心问题。那么WEEX是如何实现的?目前WEEX已经完全开源,并捐给Apache基金会,我们可以通过分析其源码来一探究竟。

点此查看原文:https://yq.aliyun.com/articles/376633?spm=a2c41.11181499.0.0

作者:阿里-移动云-大前端团队

传统的移动端开发,一个完整的业务需要维护三份终端代码:Android、iOS、H5,这带来了极大的开发成本以及维护成本。尤其是对处于业务初创期需要快速试错的业务以及需要支持定期运营活动的业务。所以业界也一直在探索跨平台方案,旨在通过一套代码完成各个终端的业务逻辑。相关方案经过不断演化,从早期的H5、Hybrid到如今的Cloud Native(云原生),在开发效率和用户体验上都在一点点逼近最初的设想。

早期H5和Hybrid方案的核心是利用终端的内置浏览器(webview)功能,通过开发web应用满足跨平台需求。该方案可以解决跨平台问题,同时可以提升发版效率。但其最大的弊端在于用户体验相较于native开发的app存在较大差距,经常出现页面卡顿,加载慢等问题。

于是后来业界开始探索依旧利用web技术栈开发出媲美原生体验app的方案,于是以WEEX为代表云原生开发框架开始出现。所谓云原生(Cloud Native)指可以通过云端快速发布(与远程web应用发布流程类似),同时还可以达到媲美原生App体验的方案。WEEX依旧采取传统的web开发技术栈进行开发,同时app在终端的运行体验不输native app。其同时解决了开发效率、发版速度以及用户体验三个核心问题。那么WEEX是如何实现的?目前WEEX已经完全开源,并捐给Apache基金会,我们可以通过分析其源码来一探究竟。

WEEX框架主要分为两部分:

前端JavaScript框架
Native SDK

本文主要探讨Native SDK的核心原理,其前端JavaScript框架会在后续的文章中进行介绍。

1 整体架构

首先来看下WEEX开发的整体架构:

图片描述

从上图中可以看到weex的大致工作流程:

研发人员利用web技术栈开发weex file,打包成JS Bundle,然后部署到服务器上
终端通过网络获取JS Bundle,然后在本地执行该JS Bundle

终端上提供了JS的执行引擎(JSCore)用于执行远程加载到JS Bundle

JS执行引擎执行JS Bundle,并将相关渲染指令以及其他需要利用native能力的指令通过JS-Native Bridge透出

JS-Native Bridge将渲染指令分发到native(Andorid、iOS)渲染引擎,由native渲染引擎完成最终的页面渲染

看完上述整体架构后,可以大致理解为何WEEX可以达到媲美原生的体验,因为其页面渲染并不是像H5方案一样接入浏览器的渲染能力,而是原生渲染,所以本质上渲染出来的页面就是一个native页面。

接下来我们再来将端上的模块进行详细的拆分:

图片描述

如上图所示,WEEX NATIVE SDK大致可以分为如下几个层级:

JS执行层:

JS执行引擎:JSCore,解释并执行JS Bundle
main.js:提供WEEX runtime,SDK初始化,JS Core会首先加载main.js,为js bundle提供weex runtime
Bridge层:提供JS和Native的双向通信能力
Dom层:维护页面Dom结构
Render层:完成页面渲染
native组件库:本地UI组件库,每一个组件对应一个html标签,所以当我们在weex开发过程中使用到的各种标签:div、text、image等等,最终都被转化成为了一个native的控件
module manager、module库:功能模块管理层
WXSDKManger、WXSDKEngine:SDK全局环境维护
WXSDKInstance:weex 实例,一个js bundle对应一个weex实例

2 WEEX SDK初始化

有了上述大致架构和功能划分后,我们以一个实际的例子来分析WEEX NATIVE SDK的运行逻辑。首先来看下WEEX SDK在初始化阶段都做了哪些准备工作。

这里以Andorid代码为例进行分析:WEEX的初始化通常放在Application中,其初简化的初始化逻辑入如下:

public class WXApplication extends Application {@Overridepublic void onCreate() {super.onCreate();initWeex();......}private void initWeex() {// 自定义相关配置InitConfig config=new InitConfig.Builder().setImgAdapter(new ImageAdapter()) // 自定义图片适配器.build();WXSDKEngine.initialize(this,config);// register moduletry {WXSDKEngine.registerModule("testmodule", TestModule.class); // 注册自定义模块WXSDKEngine.registerModule("event", WXEventModule.class);WXSDKEngine.registerComponent("richtext", RichText.class); // 注册自定义UI组件......} catch (WXException e) {e.printStackTrace();}}
}

从代码中可以看到,weex的初始化比较简单,主要完成两件事:

完成初始化配置:比如指定相关适配器,比如图片请求适配器
注册自定义的UI组件和功能模块

剩下的事情都交给WEEX SDK来完成了,那么接下来就来看下WEEX SDK都做了些什么?

图片描述

具体代码在WXSDKEngine.doInitInternal:

 private static void doInitInternal(final Application application,final InitConfig config){WXEnvironment.sApplication = application;WXEnvironment.JsFrameworkInit = false;WXBridgeManager.getInstance().post(new Runnable() {@Overridepublic void run() {long start = System.currentTimeMillis();WXSDKManager sm = WXSDKManager.getInstance();sm.onSDKEngineInitialize();if(config != null ) {sm.setInitConfig(config);if(config.getDebugAdapter()!=null){config.getDebugAdapter().initDebug(application);}}WXSoInstallMgrSdk.init(application,sm.getIWXSoLoaderAdapter(),sm.getWXStatisticsListener());boolean isSoInitSuccess = WXSoInstallMgrSdk.initSo(V8_SO_NAME, 1, config!=null?config.getUtAdapter():null);if (!isSoInitSuccess) {return;}sm.initScriptsFramework(config!=null?config.getFramework():null);WXEnvironment.sSDKInitExecuteTime = System.currentTimeMillis() - start;WXLogUtils.renderPerformanceLog("SDKInitExecuteTime", WXEnvironment.sSDKInitExecuteTime);}});register();}

这是WEEX SDK的初始化逻辑,其主要做了以下几件事:

初始化WXBridge,同时启动WXBridge线程,待接收指令。WXBridge在Android的实现本质上是一个基于HandlerThread的异步任务处理线程

initSo:加载so文件,即JS执行引擎

initScriptsFramework:加载SDK中的main.js,完成weex runtime的初始化

register:注册SDK自带的UI组件和功能模块

3 页面渲染

WEEX SDK在完成了初始化之后,即可开始渲染页面了。接下来我们以如下这JS代码为例,来介绍页面的渲染逻辑:

图片描述

JS代码比较简单,逻辑就不介绍了。接下来重点介绍,当终端获取到如上图右侧的js bundle后,如何进行加载、渲染以及后续的相关逻辑执行。

3.1 weex实例创建

实际上当WEEX SDK获取到JS Bundle后,第一时间并不是立马渲染页面,而是先创建WEEX的实例:

图片描述
这幅时序图中有两个主要逻辑:

创建createInstance:创建一个weex实例,每一个JS bundle对应一个实例,同时每一个实例都有一个instance id。由于所有的js bundle都是放入到同一个JS执行引擎中执行,那么当js执行引擎通过WXBridge将相关渲染指令传出的时候,需要通过instance id才能知道该指定要传递给哪个weex实例

execJs:在创建实例完成后,接下来才是真正将js bundle交给js执行引擎执行

3.2 页面渲染

在实例创建完成后,接下来就是页面渲染了。首先来看下页面渲染的整体流程:

图片描述

js bundle涉及dom操作的执行都会被weex-vue-framework转化成native dom api, 前端框架vue是基于virtual dom api,而weex的前端框架:weex-vue-framework的核心逻辑就是将vue的virtual-dom转换成Native DOM API
weex终端的执行引擎在执行到Native DOM API后,则会将其转化为Platform API,说白了就是通过WXBridge将Native DOM API以约定的方式转发给native渲染引擎,完成页面渲染
图片描述

可以看到,在js执行引擎创建好weex实例后,会执行对应的JS Bundle,并在执行到platform api的时候将其通过wxbridge,发送给DomManager。相关代码可参考:com.taobao.weex.bridge.WXBridge

3.2.1 createbody

图片描述

一个页面的DOM结构最外层是body,所以创建页面一开始就是createbody,整个create body的过程大致可以分为以下几个步骤:

WXBridge将create body指令发送给WXDom模块。WXDom是另一个异步线程,负责维护页面的Dom树

WXDom创建一个新的dom树,同时创建body节点

WXDom将create body指令传递给WXRenderManager渲染引擎,渲染引擎主要完成如下几件事:

初始化一个组件实例,称为mGodComponent
generateComponentTree:由于一个WEEX页面就是由多个UI组件(Component)构成的一棵树,所以渲染引擎会初始化组件树
创建view

3.3.2 addElement

图片描述

创建完body后,需要在body中添加一个text组件,指向该操作的Native DOM API为addElement,其具体操作为:

WXDomManager:更新本地dom树,添加text节点
WXRenderManager:本地渲染引擎添加相关组件:

从已注册的组件中找到text对应的组件,并实例化
将初始化完成的text组件添加到body所对应的view之上
给text组件设定布局、添加监听事件
加入数据绑定
在此一个带有一个text标签的简单页面才算是渲染完成。值得一提的是,在WXRenderManager创建组件时,需要在本地已注册的组件中需要标签对应的组件,此处标签对应的组件为com.taobao.weex.ui.component.WXText,其本质上是一个TextView。从这里可以发现,其实我们在JS Bundle中指定的各种标签,其实都最终被转化为了一个native的控件。这也就是为什么用WEEX开发出来的app,本质上还是一个Native App。

其他的对应关系还有:

div 对应WXDiv
image 对应WXImage
list对应WXListComponent
a对应WXA
……
4 总结
通过前文的介绍,相信大家对WEEX有了一个初步的系统认识。简单来说,WEEX放弃了传统的Webview,而是搭建了一个native化的浏览器,因为用native的方式实现了一个浏览器的大部分核心组成成分:

JS 执行引擎
渲染引擎
DOM树管理
网络请求,持久层存储等等能力

另外为了保证整个SDK的运行效率,SDK维护了三个线程:

bridge线程:完成js到native之间的通信
dom线程:完成dom结构的构建
渲染线程:完成UI渲染,也就是UI线程

以上就是WEEX SDK的大致框架和核心逻辑,篇幅有限,无法面面俱到,只是希望通过该文想大家展示WEEX基于WEB技术栈开发native app的原理。文章内容如有偏颇,欢迎大家指正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/522868.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是java枚举_什么是java枚举

什么是java枚举?java 枚举的定义与用法一、枚举的定义:枚举是一种特殊的数据类型,之所以特殊是因为它既是一种类(class)类型却又比类型多了些特殊的约束,但是这些约束的存在也造就了枚举类型的简洁,安全性以及便捷性。…

基于阿里云Serverless架构下函数计算的最新应用场景详解(一)

摘要: Serverless概念是近年来特别火的一个技术概念,基于这种架构能构建出很多应用场景,适合各行各业,只要对轻计算、高弹性、无状态等场景有诉求的用户都可以通过本文来普及一些基础概念,看看这些场景是否对用户有一些…

浪潮云完成6亿元B轮融资,正推进上市;VMware收购AI初创公司Bitfusion;小爱同学App在苹果应用商店下架……...

关注并标星星CSDN云计算极客头条:速递、最新、绝对有料。这里有企业新动、这里有业界要闻,打起十二分精神,紧跟fashion你可以的!每周三次,打卡即read更快、更全了解泛云圈精彩newsgo go go 华为Mate30 Lite贴膜曝光&am…

基于阿里云Serverless架构下函数计算的最新应用场景详解(二)

摘要: Serverless概念是近年来特别火的一个技术概念,基于这种架构能构建出很多应用场景,适合各行各业,只要对轻计算、高弹性、无状态等场景有诉求的用户都可以通过本文来普及一些基础概念,看看这些场景是否对用户有一些…

增长黑客系列:今天比昨天增长多少?快使用环比函数来分析日志

摘要: 增长黑客系列:今天比昨天增长多少?快使用环比函数来分析日志 在我们平时分析业务时,一个最重要的指标就是,今天比昨天增长多少,本周比上周增长多少;或者同上一个周期相比增长最大的分类是…

云计算将会让数据中心消失?

戳蓝字“CSDN云计算”关注我们哦!作者 | 王洪鹏出品 | CSDN云计算(ID:CSDNcould)近年来企业应用云化明显,越来越多的企业开始将自己的公司业务转移到云平台之上,可能是迁到公有云,也可能是私有云…

巧用 Img / JavaScript 采集页面数据

摘要: 当我们有一个新内容时(例如新功能、新活动、新游戏、新文章),作为运营人员总是迫不及待地希望能尽快传达到用户,因为这是获取用户的第一步、也是最重要的一步。 点此查看原文:http://click.aliyun.com/m/40929/…

时间序列数据的存储和计算 - 开源时序数据库解析

摘要: Prometheus 开源时序数据库解析的系列文章在之前已经完成了几篇,对比分析了Hbase系的OpenTSDB、Cassandra系的KairosDB、BlueFlood及Heroic,最后是tsdb ranking top 1的InfluxDB。 点此查看原文:http://click.aliyun.com/m/…

flowable modler为任务节点增加自定义属性

如何在modler设计器中为任务节点,添加自定义的属性。 文章目录1、modler设计器中所有元素的定义2、flowable如何处理stencilset_bpmn.json文件3、为UserTask任务节点添加一个扩展属性3.1. 添加属性的名称3.2. 为任务节点添加扩展属性3.3. 查看效果1、modler设计器中…

微软对OpenAI投资10亿美元欲开发AI技术;华晨宝马宣布建成全球首个5G汽车生产基地;传苹果将收购英特尔调制解调器芯片业务...

关注并标星星CSDN云计算极客头条:速递、最新、绝对有料。这里有企业新动、这里有业界要闻,打起十二分精神,紧跟fashion你可以的!每周三次,打卡即read更快、更全了解泛云圈精彩newsgo go go 索尼Xperia 1R信息曝光&…

java se 与j2se_javaSE和 j2SE的区别?

javaSE和 j2SE的区别?关注:71 答案:4 mip版解决时间 2021-01-28 18:29提问者耍硪ミ倪配么2021-01-27 20:19javaSE和 j2SE的区别?最佳答案二级知识专家自然卷的气质2021-01-27 21:53JavaEE 比 se多了许多包,用于开发大规模的,分布式的Java应用/服务器…

[高速通道进阶一]如何理解高速通道的就近接入和一点接入连接全球

摘要: 经常有用户问,我在上海有个IDC,在北京有个VPC,我想通过专线把IDC和VPC连接起来,我是不是要找运营商直接拉一根上海到北京的专线?其实不是这样的,用户只需要接入到最近的接入点即可。高速通…

Flowable决策任务(decision task)

摘要:Flowable中引入了一个decision task(我们可以将其称之为决策任务)。在讲解decision task之前,我们不妨看一下dmn引擎。因为如果大家不了解dmn,那肯定不知道如何使用decision task了。 dmn是decision Modeling Not…

5G精华问答 | 5G技术已经成熟了吗?

1G时我们用手机打电话,2G时我们能互发短信、看文字信息,3G时上网看图片,而4G时我们看视频和直播,从1G到4G,不仅信号越来越好,安全性越来越高,上网也越来越快了。1Q:5G技术已经成熟了…

PyODPS DataFrame:统一的数据查询语言

摘要: 前几天,PyODPS发布了0.7版本,这篇文章给大家介绍下PyODPS新版本带来的重要特性。 之前也有若干篇文章介绍过了,我们PyODPS DataFrame是延迟执行的,在调用立即执行的方法,比如execute、persist等之前&…

AliOS Things 持续集成(CI)系统介绍

摘要: AliOS Things在快速的迭代进化之中,如何保证提交的代码质量,并保证在各个硬件平台上的稳定性,是一个非常大的挑战。同时物联网硬件碎片化,资源紧张,对持续集成(CI)系统也提出了…

从青铜到王者,助力企业轻松上云的四大绝招!

戳蓝字“CSDN云计算”关注我们哦!IBM在7月份发生了很多大事,其中这两件你知道吗?第一,IBM(NYSE: IBM)与美国电话电报公司(AT&T)(NYSE: T)达成一项为期多年的战略联盟…

PyODPS 中使用 Python UDF

摘要: PyODPS 中使用 Python UDF 包含两方面,一个是直接使用,也就是在 MaxCompute SQL 中使用;一个是间接的方式,也就是 PyODPS DataFrame,这种方式你不需要直接写 Python UDF,而是写普通的 Pyt…

无服务器计算,如何节省时间和成本?

戳蓝字“CSDN云计算”关注我们哦!译者 | 风车云马出品 | CSDN云计算(ID:CSDNcould)为了解决面临的业务问题,通常需要开发人员花费一定的时间编写完代码,再交由运维工程师确保正常的运行,整个过程…

一张图看懂阿里云新发布的物联网设备上云神器——HiTSDB + IoT套件

近日,阿里云针对物联网企业遇到的设备认证困难、安全问题突出等问题,发布了HiTSDB IoT 套件的一体化解决方案,能够支持物联设备快速上云,高效设备管理,数据安全,低成本海量数据存储,实时掌握设备…