天天看點

WebKit – WebKit For AndroidWebKit – WebKit For Android 一、WebKit簡介二、WebKit目錄結構三、 WebKit子產品架構 四、基本操作分析

WebKit – WebKit For Android

本文轉載自:

WebSite: http://www.jjos.org/

作者: 姜江

一、WebKit簡介

WebKit是一個開源的浏覽器網頁排版引擎,包含WebCore排版引擎和JSCore引擎。 WebCore和JSCore引擎來自于KDE項目的KHTML和KJS開源項目。Android平台的Web 引擎架構采用了WebKit項目中的WebCore和JSCore部分,上層由Java語言封裝,并且作 為API提供給Android應用開發者,而底層使用WebKit核心庫(WebCore和JSCore)進行 網頁排版。

二、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互相調用,如下圖所示:

WebKit – WebKit For AndroidWebKit – WebKit For Android 一、WebKit簡介二、WebKit目錄結構三、 WebKit子產品架構 四、基本操作分析

3.1 Java層架構

3.1.1 主要類關系

WebKit子產品的 Java層一共由 41個檔案組成,其中主要的類關系如下圖所示:

WebKit – WebKit For AndroidWebKit – WebKit For Android 一、WebKit簡介二、WebKit目錄結構三、 WebKit子產品架構 四、基本操作分析
  1. WebView

WebView類是 WebKit子產品 Java層的視圖類,所有需要使用 Web浏覽功能的 Android應用程式都要建立該視圖對象顯示和處理請求的網絡資源。目前, WebKit子產品支援 HTTP、 HTTPS、 FTP以及 javascript請求。 WebView作為應用程式的 UI接口,為使用者提供了一系列的網頁浏覽、使用者互動接口,客戶程式通過這些接口通路 WebKit核心代碼。

  1. WebViewDatabase

WebViewDatabase是 WebKit子產品中針對 SQLiteDatabase對象的封裝,用于存儲和擷取運作時浏覽器儲存的緩沖資料、曆史通路資料、浏覽器配置資料等。該對象是一個單執行個體對象,通過 getInstance方法擷取 WebViewDatabase的執行個體。 WebViewDatabase是 WebKit子產品中的内部對象,僅供 WebKit架構内部使用。

  1. WebViewCore

WebViewCore類是 Java層與 C層 WebKit核心庫的互動類,客戶程式調用 WebView的網頁浏覽相關操作會轉發給 BrowserFrame對象。當 WebKit核心庫完成實際的資料分析和處理後會回調 WebViweCore中定義的一系列 JNI接口,這些接口會通過 CallbackProxy将相關事件通知相應的 UI對象。

  1. CallbackProxy

CallbackProxy是一個代理類,用于 UI線程和 WebCore線程互動。該類定義了一系列與使用者相關的通知方法,當 WebCore完成相應的資料處理,則會調用 CallbackProxy類中對應的方法,這些方法通過消息方式間接調用相應處理對象的處理方法。詳細的處理流程在下文中會具體分析。

  1. BrowserFrame

BrowserFrame類負責 URL資源的載入、通路曆史的維護、資料緩存等操作,該類會通過 JNI接口直接與 WebKit C層庫互動。

  1. JWebCoreJavaBridge

該類為 Java層 WebKit代碼提供與 C層 WebKit核心部分的 Timer和 Cookies操作相關的方法。

  1. DownloadManagerCore

下載下傳管理核心類,該類負責管理網絡資源下載下傳,所有的 Web下載下傳操作均有該類同一管理。該類執行個體運作在 WebKit線程當中,與 UI線程的互動是通過調用 CallbackProxy對象中相應的方法完成。

  1. WebSettings

該對象描述了 WEB浏覽器通路相關的使用者配置資訊。

  1. DownloadListener

下載下傳偵聽接口,如果客戶代碼實作該接口,則在下載下傳開始、失敗、挂起、完成等情況下, DownloadManagerCore對象會調用客戶代碼中實作的 DwonloadListener方法。

  1. WebBackForwardList

WebBackForwarList對象維護着使用者通路曆史記錄,該類為客戶程式提供操作通路浏覽器曆史資料的相關方法。

  1. WebViewClient

WebViewClient類定義了一系列事件方法,如果 Android應用程式設定了 WebViewClient派生對象,則在頁面載入、資源載入、頁面通路錯誤等情況發生時,該派生對象的相應方法會被調用。

  1. WebBackForwardListClient

WebBackForwardListClient對象定義了對通路曆史操作時可能産生的事件接口,當使用者實作了該接口,則在操作通路曆史時(通路曆史移除、通路曆史清空等)使用者會得到通知。

  1. WebChromeClient

WebChromeClient類定義了與浏覽視窗修飾相關的事件。例如接收到 Title、接收到 Icon、進度變化時, WebChromeClient的相應方法會被調用。

3.1.2 主要類的設計

3.1.2.1 資料載入器的設計

WebKit子產品的 Java部分架構中使用資料載入器來加載相應類型的資料,目前有 CacheLoader、 DataLoader以及 FileLoader三類載入器,他們分别用于處理緩存資料、記憶體據,以及檔案資料的載入操作。 Java層( WebKit子產品)所有的載入器都從 StreamLoader繼承(其父類為 Handler),由于 StreamLoader類的基類為 Handler類,是以在構造載入器時,會開啟一個事件處理線程,該線程負責實際的資料載入操作,而請求線程通過消息的方式驅動資料的載入。下圖是資料載入器相關類的類圖結構:

WebKit – WebKit For AndroidWebKit – WebKit For Android 一、WebKit簡介二、WebKit目錄結構三、 WebKit子產品架構 四、基本操作分析

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互動過程:

WebKit – WebKit For AndroidWebKit – WebKit For Android 一、WebKit簡介二、WebKit目錄結構三、 WebKit子產品架構 四、基本操作分析

上圖中綠色部分是 BrowserFrame處理進度變更事件時,調用 CallbackProxy對象通知視圖變更狀态的操作,在這裡省略。途中灰色部分表示 C層代碼,而白色部分表示 Java層代碼。

3.2 C層架構

3.2.1 C類與 Java類的關系

1 . BrowserFrame

與 BrowserFrame Java類相對應的 C++類為 FrameBridge,該類為 Dalvik虛拟機回調 BrowserFrame類中定義的本地方法進行了封裝。與 BrowserFrame中回調函數( Java層)相對應的 C層結構定義如下:

WebKit – WebKit For AndroidWebKit – WebKit For Android 一、WebKit簡介二、WebKit目錄結構三、 WebKit子產品架構 四、基本操作分析

該結構作為 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的時候被建立,他們的關系如下圖所示:

WebKit – WebKit For AndroidWebKit – WebKit For Android 一、WebKit簡介二、WebKit目錄結構三、 WebKit子產品架構 四、基本操作分析

上圖中标注為深綠色的 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緩沖。

初始化過程的序列圖如下圖所示:

WebKit – WebKit For AndroidWebKit – WebKit For Android 一、WebKit簡介二、WebKit目錄結構三、 WebKit子產品架構 四、基本操作分析

初始化完成後 Java層和 C層類圖關系如下圖所示

WebKit – WebKit For AndroidWebKit – WebKit For Android 一、WebKit簡介二、WebKit目錄結構三、 WebKit子產品架構 四、基本操作分析

上圖中淡綠色的類表示 Java層,而灰色類表示 C層。

4.2 資料載入

4.2.1 載入網絡資料

客戶代碼中可以使用 WebView類的 loadUrl方法,請求通路指定的 URL網頁資料。 WebView對象中儲存着 WebViewCore的引用,由于 WebView屬于 UI線程,而 WebViewCore屬于背景線程,是以 WebView對象的 loadUrl被調用時,會通過消息的方式将 URL資訊傳遞給 WebViewCore對象,該對象會調用成員變量 mBrowserFrame的 loadUrl方法,進而調用 WebKit庫完成資料的載入。其調用函數序列如下所示:

WebKit – WebKit For AndroidWebKit – WebKit For Android 一、WebKit簡介二、WebKit目錄結構三、 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對象有如下幾個:

  1. Picture類

該類對 SGL封裝,其中變量 mNativePicture實際上是儲存着 SkPicture對象的指針。 WebViewCore中定義了兩個 Picture對象,當作雙緩沖處理,在調用 webKitDraw方法時,會交換兩個緩沖區,加速重新整理速度。

  1. WebView類

該類接受使用者互動相關的操作,當有滾屏、視窗遮蓋、使用者點選頁面按鈕等相關操作時, WebView對象會與之相關的 WebViewCore對象發送 VIEW_SIZE_CHANGED消息。當 WebViewCore對象接收到該消息後,将建構時建立的 mContentPictureB重新整理到螢幕上,然後将 mContentPictureA與之交換。

  1. 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方法的調用,完成一次網頁資料的繪制過程。

~~~ END ~~~

From Jelly's Blog , post WebKit – WebKit For Android