《深入理解Android》一2.1 浏览器工作原理概述

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介:

本节书摘来自华章出版社《深入理解Android》一书中的第2章,第2.1节,作者孟德国 王耀龙 周金利 黎欢,更多章节内容可以访问云栖社区“华章计算机”公众号查看

2.1 浏览器工作原理概述

众所周知,万维网(World Wide Web,WWW)以统一资源定位符(Uniform Resource Locator,URL)作为地址空间编码,以超文本传送协议(HyperText Transfer Protocol,HTTP)请求和应答,以超文本标记语言(HyperText Markup Language,HTML)记录并以超链接(hyperlink)互相关联起来的网页(web page)文档作为内容单元,构成了人类有史以来最为庞大的资料信息库。浏览器(browser application)即是专门用来访问和浏览万维网页面的客户端软件,也是现代计算机系统中应用最为广泛的软件之一,其重要性不言而喻。浏览器内部最主要也是最重要的模块是负责页面渲染的排版引擎(layout engine),也可称作浏览器的内核(kernel),其余的部分可统称为浏览器的外壳(browser shell)。
下面将从页面、排版引擎和浏览器外壳应用三个方面对万维网和浏览器技术的基本概念和原理逐一地做简单介绍。

2.1.1 页面

现代Web Page通常由三部分组成:描述页面结构和内容的HTML语言,控制页面动态逻辑的JavaScript脚本,设定页面风格样式的层叠样式表(Cascading Style Sheets,CSS)。
HTML是为创建和描述可在浏览器中展现的网页信息而设计的一种文本格式标记语言,最初于1982年由Tim Berners-Lee创建,后来成为国际标准,由万维网联盟(W3C)维护。HTML由SGML(Standard Generalized Markup Language)简化发展而来,能够结构化地表示文档的构成和内容(如标题、段落、文本、表格),以及一定的外观(如宽、高、颜色)和语义(如注释、链接)。HTML页面由多种尖括号<>包围起来的标签元素以树形结构组成,其顶级标签为,内容标签为

,标签中可内嵌JavaScript脚本和CSS。当前W3C推荐使用的HTML标准有XHTML 1.1、HTML 4.01和HTML 5。
JavaScript是一种内置于浏览器的动态、弱类型、基于原型的网页脚本语言。一般来说,完整的JavaScript应该包括以下几个部分:
ECMAScript:描述了该语言的语法和基本对象;
文档对象模型(DOM):描述处理网页内容的方法和接口;
浏览器对象模型(BOM):描述与浏览器进行交互的方法和接口。
JavaScript的出现使得网页由单纯的静态HTML变成动态可编程的DHTML,开发者可用JavaScript来完成读写DOM,向页面添加交互行为,对浏览器事件做出响应,创建和发起网络请求等许多工作。
层叠样式表(CSS)的发明是为了将网页的内容描述与显示风格的描述分隔出来,HTML中只包含结构和内容的描述信息,CSS则只包含样式的描述信息。单独把一些显示风格信息如字体颜色、背景、排版方式等统一放在CSS文本中,可以大大简化HTML文件,同时增强可读性和修改灵活性。
Web Page一般由前端(front end)开发设计人员直接编写或者由服务器端的脚本动态生成,通过Web服务器以HTTP协议发布,供浏览器访问,这种方式即是通常所说的B/S架构(Browser/Server Architecture)。

2.1.2 内核

浏览器的内核或称排版引擎,负责请求网络页面资源加以解析排版并呈现给用户。从资源的下载到最终的页面展现,可简单地理解成一个线性串联的变换过程的组合,原始输入为URL地址,最终输出为页面Bitmap,中间依次经过了Loader、Parser、Layout和Paint模块,如图2-1所示。

image

  1. Loader
    Loader模块(如图2-2所示)负责处理所有的HTTP请求以及网络资源的缓存,相当于是从URL输入到Page Resource输出的变换过程。HTML页面中通常有外链的JS/CSS/Image资源,为了不阻塞后续解析过程,一般会有两个IO管道同时存在,一个负责主页面下载,一个负责各种外链资源的下载。

image

 虽然大部分情况下不同资源可以并发下载异步解析(如图片资源可以在主页面解析显示完成后再被显示),但JS脚本可能会要求改变页面,因此有时保持执行顺序和下载管道后续处理的阻塞是不可避免的。

  1. Parser
    Parser模块主要负责解析HTML页面,完成从HTML文本到HTML语法树再到文档对象树(Document Object Model Tree,DOM Tree)的映射过程。

HTML语法树生成如图2-3所示是一个典型的语法解析过程,可以分成两个子过程:词法解析和语法解析。词法解析按照词法规则(如正则表达式)将HTML文本分割成大量的标记(token),并去除其中无关的字符如空格。语法解析按照语法规则(如上下文无关文法)匹配Token序列生成语法树,通常有自上而下和自下而上两种匹配方式。
浏览器内核中对HTML页面真正的内部表示并不是语法树,而是W3C组织规范的文档对象模型 (Document Object Model,DOM)。DOM也是树形结构,以Document对象为根。DOM节点基本和HTML语法树节点一一对应,因此在语法解析过程中,通常直接生成最终的DOM树。下面这个HTML文档对应的语法树如图2-4所示,而实际构建的DOM树如图2-5所示。

image

<html> 
 <body>
    <p>Hello, World</p>
    <div><img src=”example.png”/><div/>
 </body>
</html>

image

 不同的页面标签对应不同类型的DOM树节点,如

标签会对应HTMLDiv-Element。DOM节点类型构成一个继承体系,详情可参见WebKit源码中WebCore/dom和WebCore/html两个目录。
页面中所有的CSS由样式表CSSStyleSheet集合构成,而CSSStyleSheet是一系列CSSRule的集合,每一条CSSRule则由选择器CSSStyleSelector部分和声明CSSStyleDeclaration部分构成,而CSSStyleDeclaration是CSS属性和值的Key-Value集合。图2-6显示了某一CSS样式表经过CSSParser解析后在浏览内核中的基本表示。
CSS解析完毕后会进行CSSRule的匹配过程,即寻找满足每条CSS规则Selector部分的HTML元素,然后将其Declaration部分应用于该元素。实际的规则匹配过程会考虑到默认和继承的CSS属性、匹配的效率及规则的优先级等因素。

image

JavaScript一般由单独的脚本引擎解析执行,它的作用通常是动态地改变DOM树(比如为DOM节点添加事件响应处理函数),即根据时间(timer)或事件(event)映射一棵DOM树到另一棵DOM树。
简单来说,经过了Parser模块的处理,内核把页面文本转换成了一棵节点带CSS Style、会响应自定义事件的Styled DOM树。

  1. Layout
    顾名思义,Layout过程就是排版,它包含两大过程。

步骤1:创建布局树。
布局树(或者叫做渲染树、Render Tree,如图2-7所示)和DOM树大体能一一对应,两者在内核中同时存在但作用不同。DOM树是HTML文档的对象表示,同时也作为JavaScript操纵HTML的对象接口。Render树是DOM树的排版表示,用以计算可视DOM节点的布局信息(如宽、高、坐标)和后续阶段的绘制显示。
 并非所有DOM节点都可视,也就是并非所有DOM树节点都会对应生成一个Render树节点。例如,

标签(HTMLHeadElement节点)不表示任何排版区域,因而没有对应的Render节点。同时,DOM树可视节点的CSS Style就是其对应Render树节点的Style。

image

步骤2:计算布局。
布局就是安排和计算页面中每个元素大小位置等几何信息的过程。HTML 采用流式布局模型,基本的原则是页面元素在顺序遍历过程中依次按从左至右、从上至下的排列方式确定各自的位置区域。一个HTML元素对应一个以CSS盒子模型(如图2-8所示)描述的方块区域,盒子模型决定了内容、边框和边框内外填充区(Padding、Margin)的大小。HTML元素分成两个基本类型,Inline和Block。Inline元素不会换行,按从左到右来布局。Block元素的出现意味着需要从上至下换到下一行来布局。除了这种基本的顺序按照元素的Inline和Block来进行流式布局之外,还有特殊指定的一些布局方式,如Absolute/Fixed/Relative三种定位布局以及Float浮动布局。简单情况下,布局可以顺序遍历一次Render树完成,但也有需要迭代的情况。当祖先元素的大小位置依赖于后代元素或者互相依赖时,一次遍历就无法完成布局,如Table元素的宽高未明确指定而其下某一子元素Tr指定其高度为父Table高度的30%的情况。

image

经过了Layout阶段的处理,我们把带Style的DOM树变换成包含布局信息和绘制信息的Render树,接下来的显示工作就交由Paint模块进行操作了。

  1. Paint
    Paint模块负责将Render树映射成可视的图形,它会遍历Render树调用每个Render节点的绘制方法将其内容显示在一块画布或者位图上,并最终呈现在浏览器应用窗口中成为用户看到的实际页面。每个节点对应的大小位置等信息都已经由Layout阶段计算好了,节点的内容取决于对应的HTML元素,或是文本,或是图片,或是UI控件。

通常情况下,布局和绘制是相当耗时的操作。如果DOM树每次略有改动都要重新布局和绘制一次,效率会相当低下。因此,一般浏览内核都会实现一种增量布局和增量绘制的方式。当一个DOM树节点(或者它的子节点)内容或者样式发生变化时,内核会确定其影响范围,在布局阶段会标记出受该节点布局影响的其他节点(比如可能是子节点),在绘制阶段则会标记出一个Dirty区域并通知系统重绘。
按照HTML相关规范,页面元素的CSS属性也规定了其绘制顺序,如根据不同Layer必须按顺序绘制,否则覆盖叠加效果会出现错误,如元素的边框轮廓和内容背景的绘制次序也有规定。
基本上浏览内核的工作原理即如上所述,不同浏览器的具体实现架构不尽相同,所采用的术语名称可能不一样,但都需要完成上述各个阶段的工作。例如,Mozilla Firefox浏览器使用的Gecko排版引擎主要流程如图2-9所示。
image

2.1.3 外壳

浏览器作为一个完整软件,除了对用户透明和不可见的渲染引擎作为内核外,还需要有供用户交互使用的外壳UI界面,图2-10给出了一个浏览器Shell的基本模块架构。目前的主流浏览器基本都会提供如下功能:
地址栏URI输入;
前进后退和刷新停止的控制按钮;
主页、网络导航和搜索;
历史、书签和下载管理;
多标签页浏览和会话管理;
查找、缩放和全屏;
数据持久化如Cookie、LocalStorage等;
选项设置;
插件和功能扩展。

image

由于Ajax、HTML 5等前端技术和浏览引擎的迅猛发展,今天的浏览器已经超出了展现某URL上网页内容这一基本功能的范畴,网页可作为绘图、办公、游戏、即时通信等应用的载体。Web App已经成为现实,浏览器也从单一的工具软件向Web OS的方向演进。每一个Web Page或Web App可看成对应于传统操作系统中的一个Native App,排版引擎作为Kernel执行Web App,浏览外壳作为GUI Shell供用户操作使用,多标签浏览器相当于多任务操作系统,Google的Chrome浏览器和由此演变而来的Chrome OS可看作这一想法的实施典型。图2-11描述了Chrome浏览器和WebKit排版引擎之间的层次结构和调用关系,图2-12则给出了Chrome多进程设计的核心架构。

image

image

相关文章
|
2月前
|
安全 Android开发 Kotlin
Android经典实战之SurfaceView原理和实践
本文介绍了 `SurfaceView` 这一强大的 UI 组件,尤其适合高性能绘制任务,如视频播放和游戏。文章详细讲解了 `SurfaceView` 的原理、与 `Surface` 类的关系及其实现示例,并强调了使用时需注意的线程安全、生命周期管理和性能优化等问题。
152 8
|
20天前
|
缓存 Java 数据库
Android的ANR原理
【10月更文挑战第18天】了解 ANR 的原理对于开发高质量的 Android 应用至关重要。通过合理的设计和优化,可以有效避免 ANR 的发生,提升应用的性能和用户体验。
48 8
|
6月前
|
Android开发 移动开发 小程序
binder机制原理面试,安卓app开发教程
binder机制原理面试,安卓app开发教程
binder机制原理面试,安卓app开发教程
|
1月前
|
XML 前端开发 Android开发
Android View的绘制流程和原理详细解说
Android View的绘制流程和原理详细解说
35 3
|
1月前
|
前端开发 JavaScript 异构计算
简述浏览器的渲染原理
浏览器渲染原理主要包括以下步骤:1)解析HTML文档生成DOM树;2)解析CSS生成CSSOM树;3)结合DOM与CSSOM生成渲染树;4)布局计算(回流)确定元素大小和位置;5)绘制(Paint)将节点转为图形内容;6)合成(Composite)多层图像。整个过程从文档解析到最终输出完整网页,并通过优化技术提升性能。
|
2月前
|
ARouter 测试技术 API
Android经典面试题之组件化原理、优缺点、实现方法?
本文介绍了组件化在Android开发中的应用,详细阐述了其原理、优缺点及实现方式,包括模块化、接口编程、依赖注入、路由机制等内容,并提供了具体代码示例。
45 2
|
2月前
|
编解码 前端开发 Android开发
Android经典实战之TextureView原理和高级用法
本文介绍了 `TextureView` 的原理和特点,包括其硬件加速渲染的优势及与其他视图叠加使用的灵活性,并提供了视频播放和自定义绘制的示例代码。通过合理管理生命周期和资源,`TextureView` 可实现高效流畅的图形和视频渲染。
223 12
|
1月前
|
Java 调度 Android开发
Android面试题之Kotlin中async 和 await实现并发的原理和面试总结
本文首发于公众号“AntDream”,详细解析了Kotlin协程中`async`与`await`的原理及其非阻塞特性,并提供了相关面试题及答案。协程作为轻量级线程,由Kotlin运行时库管理,`async`用于启动协程并返回`Deferred`对象,`await`则用于等待该对象完成并获取结果。文章还探讨了协程与传统线程的区别,并展示了如何取消协程任务及正确释放资源。
23 0
|
6月前
|
Web App开发 JavaScript 前端开发
浏览器与Node.js事件循环:异同点及工作原理
浏览器与Node.js事件循环:异同点及工作原理
|
3月前
|
存储 监控 数据库
Android经典实战之OkDownload的文件分段下载及合成原理
本文介绍了 OkDownload,一个高效的 Android 下载引擎,支持多线程下载、断点续传等功能。文章详细描述了文件分段下载及合成原理,包括任务创建、断点续传、并行下载等步骤,并展示了如何通过多种机制保证下载的稳定性和完整性。
107 0

热门文章

最新文章

相关实验场景

更多