原文链接:http://quanminchaoren.iteye.com/blog/1150742
===================================================================================================================================
一、WebKit简介
二、WebKit目录结构
Android平台的 WebKit模块分成 Java和 WebKit库两个部分,其目录结构如下表所示:
WebKit 模块目录结构 | |
Java 层(根目录 device\java\android\android\webkit ) | |
BrowserFrame.java | BrowserFrame对象是对 WebCore库中的 Frame对象的 Java层封装,用于创建 WebCore中定义的Frame,以及为该 Frame对象提供 Java层回调方法。 |
ByteArrayBuilder.java | ByteArrayBuilder辅助对象,用于 byte块链表的处理。 |
CachLoader.java | URL Cache载入器对象,该对象实现StreadLoader抽象基类,用于通过CacheResult对象载入内容数据。 |
CacheManager.java | Cache管理对象,负责 Java层 Cache对象管理 |
CacheSyncManager.java | Cache同步管理对象,负责同步 RAM和FLASH之间的浏览器 Cache数据。实际的物理数据操作在 WebSyncManager对象中完成。 |
CallbackProxy.java | 该对象是用于处理 WebCore与 UI线程消息的代理类。当有 Web事件产生时 WebCore线程会调用该回调代理类,代理类会通过消息的方式通知 UI线程,并且调用设置的客户对象的回调函数。 |
CellList.java | CellList定义图片集合中的 Cell,管理 Cell图片的绘制、状态改变以及索引。 |
CookieManager.java | 根据 RFC2109规范,管理 cookies |
CookieSyncManager.java | Cookies同步管理对象,该对象负责同步RAM和 Flash之间的 Cookies数据。实际的物理数据操作在基类 WebSyncManager中完成。 |
DataLoader.java | 数据载入器对象,用于载入网页数据。 |
DateSorter.java | 尚未使用 |
DownloadListener.java | 下载侦听器接口 |
DownloadManagerCore.java | 下载管理器对象,管理下载列表。该对象运行在 WebKit的线程中,通过 CallbackProxy对象与UI线程交互。 |
FileLoader.java | 文件载入器,将文件数据载入到 Frame中。 |
FrameLoader.java | Frame载入器,用于载入网页 Frame数据 |
HttpAuthHandler.java | Http认证处理对象,该对象会作为参数传递给BrowserCallback.displayHttpAuthDialog方法,与用户交互。 |
HttpDataTime.java | 该对象是处理 HTTP日期的辅助对象。 |
JsConfirmResult.java | Js确认请求对象 |
JsPromptResult.java | Js结果提示对象,用于向用户提示 Javascript运行结果。 |
JsResult.java | Js结果对象,用于用户交互 |
JWebCoreJavaBridge.java | 用 Java与 WebCore库中 Timer和 Cookies对象交互的桥接代码。 |
LoadListener.java | 载入器侦听器,用于处理载入器侦听消息。 |
Network.java | 该对象封装网络连接逻辑,为调用者提供更为高级的网络连接接口。 |
PanZoom.java | 用于处理图片缩放、移动等操作 |
PanZoomCellList.java | 用于保存移动、缩放图片的 Cell |
PerfChecker.java | 用于效率测试的功能对象??? |
SslErrorHandler.java | 用于处理 SSL错误消息。 |
StreamLoader.java | StreamLoader抽象类是所有内容载入器对象的基类。该类是通过消息方式控制的状态机,用于将数据载入到 Frame中。 |
TextDialog.java | 用于处理 html中文本区域叠加情况,可以使用标准的文本编辑而定义的特殊 EditText控件。 |
URLUtil.java | URL处理功能函数,用于编码、解码 URL字符串,以及提供附加的 URL类型分析功能。 |
WebBackForwardList.java | 该对象包含 WebView对象中显示的历史数据。 |
WebBackForwardListClient.java | 浏览历史处理的客户接口类,所有需要接收浏览历史改变的类都需要实现该接口。 |
WebChromeClient.java | Chrome客户基类, Chrome客户对象在浏览器文档标题、进度条、图标改变时候会得到通知。 |
WebHistoryItem.java | 该对象用于保存一条网页历史数据 |
WebIconDataBase.java | 图表数据库管理对象,所有的 WebView均请求相同的图标数据库对象。 |
WebSettings.java | WebView的管理设置数据,该对象数据是通过JNI接口从底层获取。 |
WebSyncManager.java | 数据同步对象,用于 RAM数据和 FLASH数据的同步操作。 |
WebView.java | Web视图对象,用于基本的网页数据载入、显示等 UI操作。 |
WebViewClient.java | Web视图客户对象,在 Web视图中有事件产生时,该对象可以获得通知。 |
WebViewCore.java | 该对象对 WebCore库进行了封装,将 UI线程中的数据请求发送给 WebCore处理,并且通过CallbackProxy的方式,通过消息通知 UI线程数据处理的结果。 |
WebViewDatabase.java | 该对象使用 SQLiteDatabase为 WebCore模块提供数据存取操作。 |
三、 WebKit模块框架
Android平台的 WebKit模块由 Java层和 WebKit库两个部分组成, Java层负责与 Android应用程序进行通信,而 WebKit类库负责实际的网页排版处理。 Java层和 C层库之间通过 JNI和 Bridge相互调用,如下图所示:
3.1 Java层框架
3.1.1 主要类关系
WebKit模块的 Java层一共由 41个文件组成,其中主要的类关系如下图所示:
-
WebView
WebView类是 WebKit模块 Java层的视图类,所有需要使用 Web浏览功能的 Android应用程序都要创建该视图对象显示和处理请求的网络资源。目前, WebKit模块支持 HTTP、 HTTPS、 FTP以及 javascript请求。 WebView作为应用程序的 UI接口,为用户提供了一系列的网页浏览、用户交互接口,客户程序通过这些接口访问 WebKit核心代码。
-
WebViewDatabase
WebViewDatabase是 WebKit模块中针对 SQLiteDatabase对象的封装,用于存储和获取运行时浏览器保存的缓冲数据、历史访问数据、浏览器配置数据等。该对象是一个单实例对象,通过 getInstance方法获取 WebViewDatabase的实例。WebViewDatabase是 WebKit模块中的内部对象,仅供 WebKit框架内部使用。
-
WebViewCore
WebViewCore类是 Java层与 C层 WebKit核心库的交互类,客户程序调用 WebView的网页浏览相关操作会转发给BrowserFrame对象。当 WebKit核心库完成实际的数据分析和处理后会回调 WebViweCore中定义的一系列 JNI接口,这些接口会通过 CallbackProxy将相关事件通知相应的 UI对象。
-
CallbackProxy
CallbackProxy是一个代理类,用于 UI线程和 WebCore线程交互。该类定义了一系列与用户相关的通知方法,当WebCore完成相应的数据处理,则会调用 CallbackProxy类中对应的方法,这些方法通过消息方式间接调用相应处理对象的处理方法。详细的处理流程在下文中会具体分析。
-
BrowserFrame
BrowserFrame类负责 URL资源的载入、访问历史的维护、数据缓存等操作,该类会通过 JNI接口直接与 WebKit C层库交互。
-
JWebCoreJavaBridge
该类为 Java层 WebKit代码提供与 C层 WebKit核心部分的 Timer和 Cookies操作相关的方法。
-
DownloadManagerCore
下载管理核心类,该类负责管理网络资源下载,所有的 Web下载操作均有该类同一管理。该类实例运行在 WebKit线程当中,与 UI线程的交互是通过调用 CallbackProxy对象中相应的方法完成。
-
WebSettings
该对象描述了 WEB浏览器访问相关的用户配置信息。
-
DownloadListener
下载侦听接口,如果客户代码实现该接口,则在下载开始、失败、挂起、完成等情况下, DownloadManagerCore对象会调用客户代码中实现的 DwonloadListener方法。
-
WebBackForwardList
WebBackForwarList对象维护着用户访问历史记录,该类为客户程序提供操作访问浏览器历史数据的相关方法。
-
WebViewClient
WebViewClient类定义了一系列事件方法,如果 Android应用程序设置了 WebViewClient派生对象,则在页面载入、资源载入、页面访问错误等情况发生时,该派生对象的相应方法会被调用。
-
WebBackForwardListClient
WebBackForwardListClient对象定义了对访问历史操作时可能产生的事件接口,当用户实现了该接口,则在操作访问历史时(访问历史移除、访问历史清空等)用户会得到通知。
-
WebChromeClient
WebChromeClient类定义了与浏览窗口修饰相关的事件。例如接收到 Title、接收到 Icon、进度变化时,WebChromeClient的相应方法会被调用。
3.1.2 主要类的设计
3.1.2.1 数据载入器的设计
WebKit模块的 Java部分框架中使用数据载入器来加载相应类型的数据,目前有 CacheLoader、 DataLoader以及FileLoader三类载入器,他们分别用于处理缓存数据、内存据,以及文件数据的载入操作。 Java层( WebKit模块)所有的载入器都从 StreamLoader继承(其父类为 Handler),由于 StreamLoader类的基类为 Handler类,因此在构造载入器时,会开启一个事件处理线程,该线程负责实际的数据载入操作,而请求线程通过消息的方式驱动数据的载入。下图是数据载入器相关类的类图结构:
StreamLoader类定义了 4个不同的消息( MSG_STATUS、 MSG_HEADERS、 MSG_DATA、 MSG_END),分别表示发送状态消息、发送消息头消息、发送数据消息以及数据发送完毕消息。该类提供了 2个抽象保护方法以及一个共有方法:setupStreamAndSendStatus保护方法主要是用于构造与通信协议相关的数据流,以及向 LoadListener发送状态。 buildHeaders方法是向子类提供构造特定协议消息头功能。所有载入器只有一个共有方法( load),因此当需要载入数据时,调用该方法即可。与数据载入流程相关的类还有 LoaderListener以及 BrowserFrame,当数据载入事件发生时, WebKit C库会更新载入进度,并且会通知 BrowserFrame, BroserFrame接收到进度条变更事件后会通过 CallbackProxy对象,通知 View类进度条数据变更。下面以 DataLoader类为例子,说明数据载入以及与 UI交互过程:
上图中绿色部分是 BrowserFrame处理进度变更事件时,调用 CallbackProxy对象通知视图变更状态的操作,在这里省略。途中灰色部分表示 C层代码,而白色部分表示 Java层代码。
3.2 C层框架
3.2.1 C类与 Java类的关系
1 . BrowserFrame
与 BrowserFrame Java类相对应的 C++类为 FrameBridge,该类为 Dalvik虚拟机回调 BrowserFrame类中定义的本地方法进行了封装。与 BrowserFrame中回调函数( Java层)相对应的 C层结构定义如下:
该结构作为 FrameBridge( C层)的一个成员变量( mJavaFrame),在 FrameBridge构造函数中,用 BrowserFrame(Java层)类的回调方法的偏移量初始化 JavaBrowserFrame结构的各个域。初始后,当 WebCore( C层)在剖析网页数据时,有Frame相关的资源改变,比如 WEB页面的主题变化,则会通过 mJavaFrame结构,调用指定 BrowserFrame对象的相应方法,通知 Java层处理。
2 . JWebCoreJavaBridge
与该对象相对应的 C层对象为 JavaBridge, JavaBridge对象继承了 TimerClient和 CookieClient类,负责 WebCore中的定时器和 Cookie管理。与 Java层 JWebCoreJavaBridge类中方法偏移量相关的是 JavaBridege中几个成员变量,在构造 JavaBridge对象时,会初始化这些成员变量,之后有 Timer或者 Cookies事件产生, WebCore会通过这些 ID值,回调对应JWebCoreJavaBridge的相应方法。
3 . LoadListener
与该对象相关的 C层结构是 struct resourceloader_t,该结构保存了 LoadListener对象 ID、 CancelMethod ID以及DownloadFiledMethod ID值。当有 Cancel或者 Download事件产生, WebCore会回调 LoadListener类中的 CancelMethod或者DownloadFileMethod。
4 . WebViewCore
与 WebViewCore相关的 C类是 WebCoreViewImpl, WebViewCoreImpl类有个 JavaGlue对象作为成员变量,在构建WebCoreViewImpl对象时,用 WebViewCore( Java层)中的方法 ID值初始化该成员变量。并且会将构建的 WebCoreViewImpl对象指针复制给 WebViewCore( Java层)的 mNativeClass,这样将 WebViewCore( Java层)和 WebViewCoreImple( C层)关联起来。
5 . WebSettings
与 WebSettings相关的 C层结构是 struct FieldIds,该结构保存了 WebSettings类中定义的属性 ID以及方法 ID,在WebCore初始化时( WebViewCore的静态方法中使用 System.loadLibrary载入)会设置这些方法和属性的 ID值。
6 . WebView
与 WebView相关的 C层类是 WebViewNative,该类中的 mJavaGlue中保存着 WebView中定义的属性和方法 ID,在WebViewNative构造方法中初始化,并且将构造的 WebViewNative对象的指针,赋值给 WebView类的 mNativeClass变量,这样WebView和 WebViewNative对象建立了关系。
3.2.2 主要类关系
与 Java层相关的 C层类如下表所示:
类 | 功能描述 |
ChromeClientAndroid | 该类主要处理 WebCore中与 Frame装饰相关的操作。例如设置状态栏、滚动条、 Javascript脚本提示框等。当浏览器中有相关事件产生,ChromeClientAndroid类的相应方法会被调用,该类会将相关的 UI事件通过 Bridge传递给Java层,由 Java层负责绘制以及用户交互方面的处理。 |
EditorClientAndroid | 该类负责处理页面中文本相关的处理,比如文本输入、取消、输入法数据处理、文本黏贴、文本编辑等操作。不过目前该类只对按键相关的时间进行了处理,其他操作均未支持。 |
ContextMenuClient | 该类提供页面相关的功能菜单,比如图片拷贝、朗读、查找等功能。但是,目前项目中未实现具体功能。 |
DragClient | 该类定义了与页面拖拽相关的处理,但是目前该类没有实现具体功能。 |
FrameLoaderClientAndroid | 该类提供与 Frame加载相关的操作,当用户请求加载一个页面时, WebCore分析完网页数据后,会通过该类调用 Java层的回调方法,通知UI相关的组件处理。 |
InspectorClientAndroid | 该类提供与窗口相关的操作,比如窗口显示、关闭窗口、附加窗口等。不过目前该类的各个方法均为空实现。 |
Page | 该类提供与页面相关的操作,比如网页页面的前进、后退等操作。 |
FrameAndroid | 该类为 Android提供 Frame管理。 |
FrameBridge | 该类对 Frame相关的 Java层方法进行了封装,当有 Frame事件产生时, WebCore通过FrameBridge回调 Java的回调函数,完成用户交互过程。 |
AssetManager | 该类为浏览器提供本地资源访问功能。 |
RenderSkinAndroid | 该类与控件绘制相关,所有的须绘制控件都需要从该类派生,目前 WebKit模块中有 Button、Combo、 Radio三类控件。 |
以上几个类会在 Java层请求创建 Web Frame的时候被建立,他们的关系如下图所示:
上图中标注为深绿色的 FrameAndroid是浏览器 Frame,一个 BrowserFrame对象对应着一个 FrameAndroid对象。而其他 8个标注为淡绿色的类,是与该 Frame显示、布局等相关的类。 WebKit模块中所有 WebCore核心代码与用户交互的操作使用 FrameAndroid对象中的 Bridge处理(回调相应的 Java方法)。
四、基本操作分析
4.1 WebKit模块初始化
Android SDK中提供了 WebView类,该类为客户提供客户化浏览显示的功能,如果客户需要加入浏览器的支持,可将该类的实例或者派生类的实例作为视图,调用 Activity类的 setContentView显示给用户。当客户代码中生成第一次生成WebView对象时,会初始化 WebKit库(包括 Java层和 C层两个部分),之后用户可以操作 WebView对象完成网络或者本地资源的访问。
WebView对象的生成主要涉及 3个类 CallbackProxy、 WebViewCore以及 WebViewDatabase。其中 CallbackProxy对象为WebKit模块中 UI线程和 WebKit类库提供交互功能, WebViewCore是 WebKit的核心层,负责与 C层交互以及 WebKit模块 C层类库初始化,而 WebViewDatabase为 WebKit模块运行时缓存、数据存储提供支持。 WebKit模块初始化流程如下:
WebView
+–创建 CallbackProxy对象
+–创建 WebViewCore对象
1–调用 System.loadLibrary载入 webcore相关类库( C层)
2–如果是第一次初始化 WebViewCore对象,创建 WebCoreTherad线程
3–创建 EventHub对象,处理 WebViewCore事件
4–获取 WebIconDatabase对象实例
5–向 WebCoreThread发送初始化消息
+–获取 WebViewDatabase实例
如上所叙,第一步调用 System.loadLibrary方法载入 webcore相关类库,该过程由 Dalvik虚拟机完成,它会从动态链接库目录中寻找 libWebCore.so类库,载入到内存中,并且调用 WebKit初始化模块的 JNI_OnLoad方法。 WebKit模块的JNI_OnLoad方法中完成了如下初始化操作:
a) 初始化 framebridge[register_android_webcore_framebridge ]
初始化 gFrameAndroidField静态变量,以及注册 BrowserFrame类中的本地方法表。
b) 初始化 javabridge[register_android_webcore_javabridge ]
初始化 gJavaBridge.mObject对象,以及注册 JWebCoreJavaBridge类中的本地方法
c) 初始化资源 loader[register_android_webcore_resource_loader ]
初始化 gResourceLoader静态变量,以及注册 LoadListener类的本地方法
d) 初始化 webviewcore[register_android_webkit_webviewcore ]
初始化 gWebCoreViewImplField静态变量,以及注册 WebViewCore类的本地方法
e) 初始化 webhistory[register_android_webkit_webhistory ]
初始化 gWebHistoryItem结构,以及注册 WebBackForwardList和 WebHistoryItem类的本地方法
f) 初始化 webicondatabase[register_android_webkit_webicondatabase ]
注册 WebIconDatabase类的本地方法
g) 初始化 websettings[register_android_webkit_websettings ]
初始化 gFieldIds静态变量,以及注册 WebSettings类的本地方法
h) 初始化 webview[register_android_webkit_webview ]
初始化 gWebViewNativeField静态变量,以及注册 WebView类的本地方法
第二步是 WebCoreThread初始化,该初始化只在第一次创建 WebViewCore对象时完成,当用户代码第一次生成WebView对象,会在初始化 WebViewCore类时创建 WebCoreThread线程,该线程负责处理 WebCore初始化事件。此时WebViewCore构造函数会被阻塞,直到一个 WebView初始化请求完毕时,会在 WebCoreThread线程中唤醒。
第三步创建 EventStub对象,该对象处理 WebView类的事件,当 WebCore初始化完成后会向 WebView对象发送事件,WebView类的 EventStub对象处理该事件,并且完成后续初始化工作。
第四步获取 WebIconDatabase对象实例。
第五步向 WebViewCore发送 INITIALIZE事件,并且将 this指针作为消息内容传递。 WebView类主要负责处理 UI相关的事件,而 WebViewCore主要负责与 WebCore库交互。在运行时期, UI线程和 WebCore数据处理线程是运行在两个独立的线程当中。 WebCoreThread线程接收到 INITIALIZE线程后,会调用消息对象参数的 initialize方法,而后唤醒阻塞的 WebViewCore Java线程(该线程在 WebViewCore的构造函数中被阻塞)。不同的 WebView对象实例有不同的 WebViewCore对象实例,因此通过消息的方式可以使得 UI线程和 WebViewCore线程解耦合。 WebCoreThread的事件处理函数,处理 INITIALIZE消息时,调用的是不同 WebView中 WebViewCore实例的 initialize方法。 WebViewCore类中的 initialize方法中会创建 BrowserFrame对象(该对象管理整个 WEB窗体,以 frame相关事件),并且向 WebView对象发送 WEBCORE_INITIALIZED_MSG_ID消息。WebView消息处理函数,会根据消息参数 1初始化指定的 WebViewCore对象,并且更新 WebViewCore的 Frame缓冲。
初始化过程的序列图如下图所示:
4.2 数据载入
4.2.1 载入网络数据
客户代码中可以使用 WebView类的 loadUrl方法,请求访问指定的 URL网页数据。 WebView对象中保存着WebViewCore的引用,由于 WebView属于 UI线程,而 WebViewCore属于后台线程,因此 WebView对象的 loadUrl被调用时,会通过消息的方式将 URL信息传递给 WebViewCore对象,该对象会调用成员变量 mBrowserFrame的 loadUrl方法,进而调用WebKit库完成数据的载入。其调用函数序列如下所示:
网络数据的载入分别由 Java层和 C层共同完成, Java层完成用户交互、资源下载等操作,而 C层主要完成数据分析(建立 DOM树、分析页面元素等)操作。由于 UI线程和 WebCore线程运行在不同的两个线程中,因此当用户请求访问网络资源时,通过消息的方式向 WebViewCore对象发送载入资源请求。在 Java层的 WebKit模块中,所有与资源载入相关的操作都是由BrowserFrame类中对应的方法完成,这些方法是本地方法,会直接调用 WebCore库的 C层函数完成数据载入请求,以及资源分析等操作。如上图所示, C层的 FrameLoader类是浏览框架的资源载入器,该类负责检查访问策略以及向 Java层发送下载资源请求等功能。在 FrameLoader中,当用户请求网络资源时,经过一系列的策略检查后会调用 FrameBridge的startLoadingResource方法,该方法会回调 BrowserFrame( Java)类的 startLoadingResource方法,完成网络数据的下载,而后BrowserFrame( Java)类的 startLoadingResource方法会返回一个 LoadListener的对象, FrameLoader会删除原有的FrameLoader对象,将 LoadListener对象封装成 ResourceLoadHandler对象,并且将其设置为新的 FrameLoader。到此完成了一次资源访问请求,接下来的任务即是 WebCore库会根据资源数据进行分析和构建 DOM,以及相关的数据结构。
4.2.2 载入本地数据
本地数据是以 data://开头的 URL表示,载入过程和网络数据一样,只不过在执行 FrameLoader类的 executeLoad方法时,会根据 URL的 SCHEME类型区分,调用 DataLoader的 requestUrl方法(参看 3.1.2.1节对载入器的分析),而不是调用handleHTTPLoad建立实际的网络通信连接。
4.2.3 载入文件数据
文件数据是以 file://开头的 URL,载入的基本流程与网络数据载入流程基本一致,不同的是在运行 FrameLoader类的executeLoad方法时,根据 SCHEME类型,调用 FileLoader的 requestUrl方法,完成数据加载(参看 3.1.2.1节对载入器的分析)。
4.3 刷新绘制
当用户拖动滚动条、有窗口遮盖、或者有页面事件触发都会向 WebViewCore( Java层)对象发送背景重绘消息,该消息会引起网页数据的绘制操作。 WebKit的数据绘制可能出于效率上的考虑,没有通过 Java层,而是直接在 C层使用 SGL库完成。与 Java层图形绘制相关的 Java对象有如下几个:
-
Picture类
该类对 SGL封装,其中变量 mNativePicture实际上是保存着 SkPicture对象的指针。 WebViewCore中定义了两个Picture对象,当作双缓冲处理,在调用 webKitDraw方法时,会交换两个缓冲区,加速刷新速度。
-
WebView类
该类接受用户交互相关的操作,当有滚屏、窗口遮盖、用户点击页面按钮等相关操作时, WebView对象会与之相关的 WebViewCore对象发送 VIEW_SIZE_CHANGED消息。当 WebViewCore对象接收到该消息后,将构建时建立的mContentPictureB刷新到屏幕上,然后将 mContentPictureA与之交换。
-
WebViewCore类
该类封装了 WebKit C层代码,为视图类提供对 WebKit的操作接口,所有对 WebKit库的用户请求均由该类处理,并且该类还为视图类提供了两个 Picture对象,用于图形数据刷新。
下面以 Web页面被鼠标拖拽的情况为例子,分析网页数据刷新过程。当用户使用手指点击触摸屏,并且移动手指,则会引发 touch事件的产生, Android平台会将 touch事件传递给最前端的视图相应( dispatchTouchEvent方法处理)。在WebView类中定义了 5种 touch模式,在手指拖动 Web页面的情况下,会触发 mMotionDragMode,并且会调用 View类的scrollBy方法,触发滚屏事件以及使视图无效(重绘,会调用 View的 onDraw方法)。 WebView视图中的滚屏事件由onScrollChanged方法响应,该方法向 WebViewCore对象发送 SET_VISIBLE_RECT事件。
WebViewCore对象接收到 SET_VISIBLE_RECT事件后,将消息参数中保存的新视图的矩形区域大小传递给nativeSetVisibleRect方法,通知 WebCoreViewImpl对象( C层)视图矩形变更( WebCoreViewImpl::setVisibleRect方法)。在setVisibleRect方法中,会通过虚拟机调用 WebViewCore的 contentInvalidate方法,该方法会引发 webkitDraw方法的调用(通过WEBKIT_DRAW消息)。在 webkitDraw方法里,首先会将 mContentPictureB对象传递给本地方法 nativeDraw绘制,而后将mContentPictureB的内容与 mContentPictureA的内容对调。在这里 mContentPictureA缓冲区是供给 WebViewCore的 draw方法使用,如果用户选择某个控件,绘制焦点框时候 WebViewCore对象的 draw方法会调用,绘制的内容保存在mContentPictureA中,之后会通过 Canvas对象( Java层)的 drawPicture方法将其绘制到屏幕上,而 mContentPictureB缓冲区是用于 built操作的, nativeDraw方法中首先会将传递的 mContentPictureB对象数据重置,而后在重新构建的 mContentPictureB画布上,将层上相关的元素绘制到该画布上。上面提到,之后会将 mContentPictureB和 mContentPictureA的内容对调,这样一次重绘事件产生时(会调用 WebView.onDraw方法)会将 mContentPictureA的数据使用 Canvas类的 drawPicture绘制到屏幕上。当webkitDraw方法将 mContentPictureA与 mContentPictureB指针对调后,会向 WebView对象发送 NEW_PICTURE_MSG_ID消息,该消息会引发 WebViewCore的 VIEW_SIZE_CHANGED消息的产生,并且会使当前视图无效产生重绘事件 (invalidate()),引发onDraw方法的调用,完成一次网页数据的绘制过程。