HarmonyOS-ArkUI: Web组件加载流程1
Web页面的加载流程概览
Web页面加载包含网络连接,资源下载, DOM解析,JavaScript代码编译执行和渲染等环节。
如图所示:
以上的流程,每一个模块都是一个比较大的话题。我们接下来按照这么个思路来学习:
- 研究各个模块究竟发生了什么,需要处理拿些事务。其中会涉及到比较大的知识块,包含。
- Http协议,TCP协议连接的环节。
- 渲染和JS编译相关的知识。
- HarmonyOS本身对于Web组件的处理流程,Web只是一个可以展示特殊内容的UI组件。所以要分
- ArkUI对组件的渲染流程
- Web容器内的内容渲染流程 以上内容估计需要很多篇文章来铺垫。
- 我们了解了各个环节的运作机制之后,便可以对各项环节进行精细优化。WebviewController的API里已经为我们提供了很多优化的API。只是太过学术所以我们要进行很多铺垫。
- 自底向上了解所有环节之后,我们统一简单描述下Web的实现架构。如果是您,您当如何从0到1设计呢?大致的模块指责和运作要了解,作为拓展。
- 这冗长的铺垫下来,我们正式的学习Web组件和WebviewController 非优化相关API!
Web,是一个比较实用,底层内容丰富的组件。其涉及的面不止在于HarmonyOS对于普通组件的渲染,而且在于Web浏览器本身内容的渲染,和底层是如何合成的画面。从这个口子可以扒出很全面的底层知识。是一个比较好的了解系统设计的例子。比普通组件的学习要有价值。
好,接下来我们开始点对点探讨主流程的每个环节。一篇接一篇连载,涉及到的副知识点也会顺带讲解。
ArkWeb组件初始化
由于ArkWeb的实现非常复杂,为了避免迷失方向,我会列出图片来展示我们学习到的位置。
在这里首先解释一下ArkWeb这个词汇。 因为如果您用ArkUI开发应用的时候,会发现压根就找不到ArkWeb这个类。用的是Web这个类。原因在于二者关系
- ArkWeb是HarmonyOS中web组件的技术架构名称。
- Web组件是一个开发接口中的具体名称。所以落实在代码处,您用的就是Web类。Web类是由ArkWeb框架技术提供支持来实现的。
下文我们依然用ArkWeb来代指浏览器。 Web只是ArkUI中的具体接口。要区分这个概念。
下图为ArkWeb组件初始化时的流程:
上图中如果之前对浏览器不了解的话,里面的词汇和概念可能一看就会模糊。我们按照图示一个一个进行解释和学习。按图索骥慢慢来。
启动Chromium内核
这节的主旨就是了解一下这个Chromium内核。
Chromium内核是一个开源的浏览器引擎,其涵盖的大致能力是
- 提供网络通信等基础能力
- 提供网页渲染的能力,支持HTML5, CSS3, WebGL等现代Web标准,确保网页兼容性
- 提供执行脚本的能力
Chromium为了实现这些能力,采用了多进程模型进行实现,其核心进程及功能如图所示:
Chromium内核各大进程模块划分及职责
上两张图主要描述了WebKit各大进程分类,以及进程包含的处理模块及职责。便于以后流程分析中有个大概的概念。
我们在后续的讲解里,多多少少都会用到上述四大进程中涉及的处理流程。到这个时候我们再详细介绍与此相关的子模块处理流程。
Harmony ArkWeb对Chromium内核的利用方式
下图为HarmonyOS中ArkWeb的进程模型:
将此图对比Chromium内核的进程模型,我们可以看出来:
Chromium内核中的浏览器进程和网络进程, HarmonyOS的ArkWeb框架里根本就没有。但是HarmonyOS却用了Chromium内核。则表明,HarmonyOS借鉴了其模块的实现逻辑,但是在架构上却没用Chromium内核的那一套。简而言之就是用到了人家的代码逻辑,但自己框架另起炉灶。
那么ArkWeb中是怎么分配的这些能力呢?
- Chromium内核中网络进程HarmonyOS没有用到, 网络部分直接交给App的应用进程及主进程里做。来处理Web组件的北向接口和回调, 网络请求,媒体服务等需要其他系统交互的功能。
- Web渲染进程(应用可以指定多个Web实例之间可以共享渲染进程,或者独立使用一个渲染进程)
- 负责运行Web渲染引擎(HTML解析,排版,绘制,渲染)
- 负责运行JavaScript执行引擎(JavaScript, Web Assembly)
- 提供接口供应用选择多Web实例间是否共享渲染进程,满足不同场景对安全性、稳定性、内存占用的诉求。默认策略:移动设备上共享渲染进程以节省内存,2in1设备上独立渲染进程提升安全与稳定性
- Web GPU进程:负责光栅化,合成送显等与GPU, RenderService交互功能,提升应用进程稳定和安全性。
预加载RosenWeb渲染线程 & 启动Compositor合成线程
RosenWeb渲染线程,执行于渲染进程中, 其主要作用是负责将DOM树转换为GPU可识别的绘制指令,并交给RenderService进行跨进程渲染。
Compositor合成线程: 执行于渲染进程中, 其主要作用是执行图层合成任务,处理动态效果,如滚动,动画的CPU指令生成, 为后续的GPU渲染准备数据。
registerCustomSchemes注册协议 & setSchemeHandler设置拦截器
图中的Scheme指的就是URL中的协议,指的是资源访问的前缀。例如前缀如果是http:// , https://则代表这个URL遵循http或者https协议。ArkWeb允许用户注册自己的自定义协议, 比如您可以处理 myCustomScheme://xxx 这样的资源请求处理规则。
这种支持有利于您实现特殊资源加载的逻辑。其核心价值在于:
- 跨域绕过:通过自定义协议拦截请求,规避浏览器同源策略限制(如加载本地
file://
协议资源)。 - 业务逻辑扩展:实现特殊资源加载(如加密文件、本地缓存资源)。
- 安全管控:限制特定协议请求的发起源(如仅允许相同协议页面发起请求)。
而setSchemeHandler拦截器的存在,则有利于您捕获到自定义协议的Url后返回一些您前后端制定好规则的内容,从而完成自定义协议的逻辑闭环。比如
- 本地资源代理:拦截
file://
请求,返回加密存储的本地文件。 - 动态响应生成:根据请求URL动态构造JSON数据,避免后端接口调用。
- 请求监控与阻断:检查非法请求并返回403错误码。
javaScriptProxy绑定Native对象
这个绑定操作核心作用是实现Web页面与ArkTs原生代码的双向通信的。也就是能保证Web页面JS调用ArkTs原生代码,和ArkTS原生代码调用Web页面JS逻辑的能力。
只有打通这两个方向,才能完成数据交互和控制交互。
采用注入机制,用过javaScriptProxy将ArkTs侧定义的对象,比如设备能力封装类,注入到Web页面的windows对象中。
实现原理
JavaScript和ArkTS是运行在不同的进程中的, 各自有各自的独立空间,那么是如何完成相互调用的呢?
二者是通过共享内存的地址映射表实现虚拟地址到物理地址的转换,避免内存访问,其实现原理与Binder类似。都是跨进程找地址。只不过实现方式不一样而已。
感兴趣可以看看Binder的原理,比较类似: Android Binder与AIDL与Service使用案例及分析_android 使用binder 示例-CSDN博客
导航流程
本图中的导航流程指的是从用户发起到页面加载完成的完整控制流程,由web组件的loadUrl触发开始,直至加载完页面内容,展示在界面上。重点在于每个环节各个进程的处理方式。
如图所示:
当导航流程开始的时候,会同时处理两个方向的事务
- 网络进程进行连接,进行资源下载
- 渲染进程初始化,以及DOM解析,和处理下载资源,这块是负责很繁杂的任务。
网络处理和渲染处理几乎并行处理。只不过是某些渲染处理环节是有些资源要等待网络进程下载到位才处理。
接下来我们先从网络部分讲起。 再讲渲染进程。由于网络连接这块涉及到很多优化部分,我们会从TCP协议讲起,之后HTTP各环节。