一、WebKit簡(jiǎn)介
WebKit
是一個(gè)開(kāi)源的瀏覽器網(wǎng)頁(yè)排版引擎,包含WebCore排版引擎和JSCore引擎。WebCore和JSCore引擎來(lái)自于KDE項(xiàng)目的KHTML和
KJS開(kāi)源項(xiàng)目。Android平臺(tái)的Web引擎框架采用了WebKit項(xiàng)目中的WebCore和JSCore部分,上層由Java語(yǔ)言封裝,并且作為
API提供給Android應(yīng)用開(kāi)發(fā)者,而底層使用WebKit核心庫(kù)(WebCore和JSCore)進(jìn)行網(wǎng)頁(yè)排版。
二、WebKit目錄結(jié)構(gòu)
Android平臺(tái)的WebKit模塊分成Java和WebKit庫(kù)兩個(gè)部分,其目錄結(jié)構(gòu)如下表所示:
Webkit 某塊目錄結(jié)構(gòu) |
Java層(根目錄device\java\android\android\webkit) |
BrowserFrame.java | BrowserFrame對(duì)象是對(duì)WebCore庫(kù)中的Frame對(duì)象的java層封裝,用于創(chuàng)建WebCore中定義的Frame,以及為該Frame對(duì)象提供Java層回調(diào)方法。
|
ByteArrayBuilder.java | ByteArrayBuilder輔助對(duì)象,用于byte塊鏈表的處理。
|
CacheLoader.java | URL Cache載入器對(duì)象,該對(duì)象實(shí)現(xiàn)SteadLoader抽象基類,用于通過(guò)CacheResult對(duì)象載入內(nèi)容數(shù)據(jù)。
|
CacheManager.java | Cache管理對(duì)象,用于java層cache對(duì)象管理。 |
CacheSyncManger.java | Cache同步管理對(duì)象,負(fù)責(zé)同步RAM和FLASH之間的瀏覽器Cache數(shù)據(jù)。實(shí)際的物理數(shù)據(jù)操作在WebSyncManager對(duì)象中完成。
|
CallbackProxy.java | 該對(duì)象用于處理WebCore與UI線程消息代理類。當(dāng)有Web事件產(chǎn)生時(shí)WebCore線程會(huì)調(diào)用該回調(diào)代理類,代理類通過(guò)消息方式通知UI線程,并且調(diào)用設(shè)置的客戶對(duì)象的回調(diào)函數(shù)。
|
CellList.java | CellList定義圖片集合中的Cell,管理Cell圖片的繪制,狀態(tài)改變以及索引。
|
CookieManager.java | 根據(jù)RFC2109規(guī)范,管理cookies.
|
DataLoader.java | 數(shù)據(jù)載入器對(duì)象,用于載入網(wǎng)頁(yè)數(shù)據(jù)。
|
DataSorter.java | 尚未使用。
|
DownloadListener.java | 下載偵聽(tīng)器接口。
|
DownloadManagerCore.java | 下載管理器對(duì)象,管理下載列表。該對(duì)象運(yùn)行于WebKit的線程中,通過(guò)CallbackProxy對(duì)象與UI線程交互。
|
FileLoader.java | 文件載入器,用于將文件載入到Frame中。
|
FrameLoader.java | Frame載入器,用于載入網(wǎng)頁(yè)Frame數(shù)據(jù)。
|
HttpAuthHandler.java | Http認(rèn)證處理對(duì)象,該對(duì)象會(huì)作為參數(shù)傳遞給BrowserCallback.displayHttpAuthDialog方法,與用戶交互。
|
HttpDataTime.java | 該對(duì)象是處理HTTP日期的輔助對(duì)象。
|
JsConfirmResult.java | Js確認(rèn)請(qǐng)求對(duì)象。
|
JsPromptResult.java | Js結(jié)果提示對(duì)象,用于向用戶提示Javascript運(yùn)行結(jié)果。
|
JsResult.java | Js結(jié)果對(duì)象,用于用戶交互。
|
JWebCoreJavaBridge.java | 用Java與WebCore庫(kù)中的Timer和Cookies對(duì)象交互的橋接代碼。
|
LoaderListener.java | 載入偵聽(tīng)器,用于處理載入器偵聽(tīng)消息。
|
NetWork.java | 該對(duì)象封裝網(wǎng)絡(luò)連接邏輯,為調(diào)用者提供更高級(jí)的網(wǎng)絡(luò)連接接口。
|
PanZoom.java | 用于處理圖片縮放、移動(dòng)等操作。
|
PanZoomCellList.java | 用于保存、縮放圖片的Cell。
|
PerfChecker.java | 用于效率測(cè)試的功能對(duì)象????
|
SslErrorHandler.java | 用于處理SSL錯(cuò)誤消息。
|
StreamLoader.java | StreamLoader抽象類是所有內(nèi)容載入器對(duì)象的基類。該類是通過(guò)消息方式控制的狀態(tài)機(jī),用于將數(shù)據(jù)載入到Frame中。 |
TextDialog.java | 用于處理html中文本區(qū)域疊加情況,可以使用標(biāo)準(zhǔn)的文本編輯而定義的特殊的EditText控件。 |
URLUtil.java | URL處理功能函數(shù),用于編碼、解碼URL字符串,以及提供附加的URL類型分析功能。 |
WebBackForwardList.java | 該對(duì)象包含WebView對(duì)象中顯示的歷史數(shù)據(jù)。
|
WebBackForwardListClient.java | 瀏覽歷史處理的客戶接口類,所有需要接收瀏覽歷史改變的類都需要實(shí)現(xiàn)該接口。 |
WebChromeClient.java | Chrome客戶基類,Chrome客戶對(duì)象在瀏覽器文檔標(biāo)題、進(jìn)度條、圖標(biāo)改變時(shí)會(huì)得到通知。 |
WebHistoryItem.java | 該對(duì)象用于保存一條網(wǎng)頁(yè)歷史數(shù)據(jù)。 |
WebIconDataBase.java | 圖標(biāo)數(shù)據(jù)庫(kù)管理對(duì)象,所有的WebView均請(qǐng)求相同的圖標(biāo)數(shù)據(jù)庫(kù)對(duì)象。 |
WebSettings.java | WebView的管理設(shè)置數(shù)據(jù),該對(duì)象數(shù)據(jù)是通過(guò)JNI接口從底層獲取。 |
WebSyncManager.java | 數(shù)據(jù)同步對(duì)象,用于RAM數(shù)據(jù)和Flash數(shù)據(jù)的同步。 |
WebView.java | Web視圖對(duì)象,用于基本的網(wǎng)頁(yè)數(shù)據(jù)載入、顯示等UI操作。 |
WebViewClient.java | Web視圖客戶對(duì)象,在Web視圖中有事件產(chǎn)生時(shí),該對(duì)象可以獲得通知。 |
WebViewCore.java | 該對(duì)象對(duì)WebCore庫(kù)進(jìn)行了封裝,將UI線程中的數(shù)據(jù)請(qǐng)求發(fā)送給WebCore處理,并且通過(guò)CallbackProxy的方式,通過(guò)消息通知UI線程數(shù)據(jù)處理結(jié)果。 |
WebViewDatabase.java | 該對(duì)象使用SQLiteDatabase為WebCore模塊提供數(shù)據(jù)存取操作。 |
三、WebKit模塊框架
Android平臺(tái)的Webkit有java層和webkit庫(kù)兩部分組成,java層負(fù)責(zé)與android應(yīng)用層進(jìn)行通信,而webkit類庫(kù)負(fù)責(zé)實(shí)際的網(wǎng)頁(yè)排版處理。Java層和C庫(kù)之間通過(guò)JNI和Bridge相互調(diào)用,如下圖所示:
3.1 java層框架
3.1.1 主要類關(guān)系
WebKit模塊的java層一共由41個(gè)文件組成,其中主要的類關(guān)系如下圖所示:
1. WebView
WebView類是WebKit模塊Java層的視圖類,所有需要使用Web瀏覽器功能的Android都需要?jiǎng)?chuàng)建該視類對(duì)象顯示和處理請(qǐng)求的網(wǎng)絡(luò)資源。
目前WebKit模塊支持HTTP、HTTPS、FTP以及javascript請(qǐng)求。WebView作為應(yīng)用程序的UI接口,為用戶提供一系列的網(wǎng)頁(yè)瀏
覽、用戶交互接口,客戶程序通過(guò)這些接口訪問(wèn)WebKit核心代碼。
2. WebViewDatabase
WebViewDatabase是WebKit模塊針對(duì)SQLiteDatabase對(duì)象的封裝,用于存儲(chǔ)和獲取運(yùn)行時(shí)瀏覽器保存的緩沖數(shù)據(jù)、歷史訪問(wèn)數(shù)
據(jù)、瀏覽器配置數(shù)據(jù)等。該對(duì)象是個(gè)單實(shí)例對(duì)象,通過(guò)getInstance方法獲取WebViewDatabase的實(shí)例。
WebViewDatabase是WebKit模塊中的內(nèi)部對(duì)象,僅供WebKit框架內(nèi)部使用。
3. WebViewCore
WebViewCore類是java層和C層WebKit核心庫(kù)的交互類,客戶程序調(diào)用WebView的網(wǎng)頁(yè)瀏覽相關(guān)操作會(huì)轉(zhuǎn)發(fā)給
BrowserFrame對(duì)象。當(dāng)WebKit核心庫(kù)完成實(shí)際的數(shù)據(jù)分析和處理后會(huì)回調(diào)WebViewCore中定義的一系列JNI接口,這些接口會(huì)通過(guò)
CallbackProxy將相關(guān)事件通知相應(yīng)的UI對(duì)象。
4. CallbackProxy
CallbackProxy是一個(gè)代理類,用于UI線程和WebCore線程交互。該類定義了一系列與用戶相關(guān)的通知方法,當(dāng)WebCore完成相應(yīng)的數(shù)
據(jù)處理,則會(huì)調(diào)用CallbackProxy類中對(duì)應(yīng)的方法,這些方法通過(guò)消息方式間接調(diào)用相應(yīng)的處理對(duì)象的處理方法。詳細(xì)的處理流程在下文中會(huì)具體分
析。
5. BrowserFrame
BrowserFrame類負(fù)責(zé)URL資源的載入、訪問(wèn)歷史的維護(hù)、數(shù)據(jù)緩存等操作,該類通過(guò)JNI接口直接與WebKit的C庫(kù)交互。
6. JWebCoreJavaBridge
該類為java層Webkit代碼提供與C層WebKit核心部分的Timer和Cookies操作相關(guān)的方法。
7. DownloadManagerCore
下載管理核心類,該類負(fù)責(zé)管理網(wǎng)絡(luò)資源下載,所有Web下載操作均由該類統(tǒng)一管理。該類實(shí)例運(yùn)行在WebKit線程當(dāng)中,與UI線程的交互是通過(guò)調(diào)用CallbackProxy對(duì)象中相應(yīng)的方法完成。
8. WebSettings
WEB瀏覽器通過(guò)該對(duì)象訪問(wèn)相關(guān)的用戶配置信息。
9. DownloadListener
下載偵聽(tīng)接口,如果用戶代碼實(shí)現(xiàn)該接口,則在下載開(kāi)始、失敗、掛起、完成等情況下,DownloadManagerCore對(duì)象會(huì)調(diào)用客戶代碼中實(shí)現(xiàn)的DownloadListener方法。
10. WebBackForwardList
WebBackForwardList 對(duì)象維護(hù)用戶訪問(wèn)歷史記錄,該類為客戶程序提供操作訪問(wèn)瀏覽器歷史數(shù)據(jù)的相關(guān)方法。
11. WebViewClient
WebViewClient類定義了一系列事件方法,如果android應(yīng)用程序設(shè)置了WebVieClient派生對(duì)象,則在網(wǎng)頁(yè)載入、資源載入、頁(yè)面訪問(wèn)錯(cuò)誤等情況發(fā)生時(shí),該派生對(duì)象的相應(yīng)方法會(huì)被調(diào)用。
12. WebBackForwardListClient
WebBackForwardListClient對(duì)象定義了對(duì)訪問(wèn)歷史操作時(shí)可能產(chǎn)生的事件接口,當(dāng)用戶實(shí)現(xiàn)該接口,則在操作訪問(wèn)歷史時(shí)(訪問(wèn)歷史移除、訪問(wèn)歷史 清空等)用戶會(huì)得到通知。
13. WebChromeClient
WebChromeClient類定義了與瀏覽器窗口修飾相關(guān)的事件。例如接收到Title、接收到Icon、進(jìn)度變化時(shí),WebChromeClient的相應(yīng)方法會(huì)被調(diào)用。
3.1.2 主要類的設(shè)計(jì)
3.1.2.1 數(shù)據(jù)載入器的設(shè)計(jì)
WebKit模塊的java部分框架中使用數(shù)據(jù)載入器來(lái)加載相應(yīng)類型的數(shù)據(jù),目前有CacheLoader、DataLoader以及
FileLoader三類載入器,他們分別用于緩存數(shù)據(jù)、內(nèi)存數(shù)據(jù)、和文件數(shù)據(jù)的載入操作。java層(WebKit模塊)所有的載入器都從
StreamLoader繼承(其父類為Handler),由于SteamLoader
類的基類為Handler類,因此在構(gòu)建載入器時(shí),會(huì)開(kāi)啟一個(gè)事件處理線程,該線程負(fù)責(zé)實(shí)際的數(shù)據(jù)載入操作,而請(qǐng)求線程通過(guò)消息的方式驅(qū)動(dòng)數(shù)據(jù)的載入。下
圖是數(shù)據(jù)載入器相關(guān)類的類圖結(jié)構(gòu):

StreamLoader類定義了4個(gè)不同的消息:
MSG_STATUS、MSG_HEADERS、MSG_DATA、MSG_END
分別表示發(fā)送狀態(tài)信息、發(fā)送消息頭消息、發(fā)送數(shù)據(jù)消息以及數(shù)據(jù)發(fā)送完畢消息。該類提供了2個(gè)抽象保護(hù)方法以及一個(gè)公有方
法:setupStreamAndSendStatus 保護(hù)方法主要是用于構(gòu)建與通信協(xié)議相關(guān)的數(shù)據(jù)流,以及向LoadListener發(fā)送狀態(tài)。
buildHeaders方法是向子類提供構(gòu)造特定協(xié)議消息頭功能。所有載入器只有一個(gè)公有方法(load),因此當(dāng)需要載入數(shù)據(jù)時(shí),調(diào)用該方法即可。與
數(shù)據(jù)載入流程相關(guān)的類還有LoaderListener以及BrowserFrame,當(dāng)數(shù)據(jù)載入事件發(fā)生時(shí),WebKit的C庫(kù)會(huì)更新載入進(jìn)度,并且會(huì)
通知BrwoserFrame,BrowserFrame接收到進(jìn)度條變更事件后通過(guò)CallbackProxy對(duì)象,通知View類進(jìn)度條數(shù)據(jù)變更。下
買你以DataLoader類為例子,說(shuō)明數(shù)據(jù)載入以及與UI交互過(guò)程(轉(zhuǎn)載者注:下圖看不清,等我搞清楚這個(gè)流程之后我再畫(huà)一個(gè)換上。):
上圖中綠色部分是BrowserFrame處理進(jìn)度變更事件時(shí),調(diào)用CallbackProxy對(duì)象通知視圖變更狀態(tài)的操作,在這里省略。圖中灰色部分表示C層代碼,而白色部分表示Java層代碼。
3.2 C層框架
3.2.1 C類與Java類的關(guān)系
1. BrowserFrame
與BrowserFrame Java類相對(duì)應(yīng)的C++類為FrameBridge,該類對(duì)Dalvik虛擬機(jī)回調(diào)BrowserFrame類中定義的本地方法進(jìn)行了封裝。與BrowserFrame中回調(diào)函數(shù)(java層)相對(duì)應(yīng)的C層結(jié)構(gòu)定義如下:
struct FrameBridge::JavaBrowserFrame
{
JavaVM* mJVM;
jobject mObj;
jmethodID mStartLoadingResource;
jmethodID mLoadStarted;
jmethodID mUpdateHistoryForCommit;
jmethodID mUpdateCurrentHistoryData;
jmethodID mReportError;
jmethodID setTitle;
jmethodID mWindowObjectCleared;
jmethodID mDidReceiveIcon;
jmethodID mUpdateVisiteHistory;
jmethodID mHandleUrl;
jmethodID mCreateWindow;
jmethodID mCloseWindow;
jmethodID mDecidePolicyForFormResubmission;
};
該結(jié)構(gòu)作為FrameBridge(C
層)的一個(gè)成員變量(mJavaFrame),在FrameBridge構(gòu)造函數(shù)中,用BrowserFrame(java
層)類的回調(diào)方法的偏移量初始化JavaBrowserFrame結(jié)構(gòu)的各個(gè)域。初始后,當(dāng)WebCore(C層)在剖析網(wǎng)頁(yè)數(shù)據(jù)時(shí),有Frame相關(guān)的
資源改變,比如WEB頁(yè)面的主題變化,則會(huì)通過(guò)mJavaFrame結(jié)構(gòu),調(diào)用指定BrowserFrame對(duì)象的相應(yīng)方法,通知Java層處理。
2. JWebCoreJavaBridge
與該對(duì)象相對(duì)應(yīng)的C層對(duì)象為JavaBridge,javaBridge對(duì)象繼承了TimerClient和CookieClient類,負(fù)責(zé)
WebCore中的定時(shí)器和Cookie管理。與Java層JWebCoreJavaBridge類中方法偏移量相關(guān)的是JavaBridge中幾個(gè)成員
變量,在構(gòu)造JavaBridge對(duì)象時(shí),會(huì)初始化這些成員變量,之后有Timer或者Cookies事件產(chǎn)生時(shí),WebCore會(huì)通過(guò)這些ID值,回調(diào)
對(duì)應(yīng)JWebCoreJavaBridge的相應(yīng)方法。
3. LoadListener
與該對(duì)象相關(guān)的C層結(jié)構(gòu)是 struct resourceloader_t,
該結(jié)構(gòu)保存了LoadListener對(duì)象ID、CancelMethod ID以及DownloadFileMethod
ID值。當(dāng)有Cancel或者Download事件產(chǎn)生,WebCore會(huì)回調(diào)LoadListener類中的CancelMethod或者
DownloadFileMethod。
4. WebViewCore
與WebViewCore相關(guān)的C類是WebCoreViewImpl,
WebViewCoreImpl類有個(gè)JavaGlue對(duì)象作為成員變量,在構(gòu)建WebCoreViewImpl對(duì)象時(shí),用
WebViewCore(java層)中的方法ID值初始化該成員變量。并且將構(gòu)建的WebCoreViewImpl對(duì)象指針賦值給
WebViewCore(java層)的mNativeClass,這樣將WebViewCore(java層)和WebViewCoreImpl(C
層)關(guān)聯(lián)起來(lái)。
5. WebSettings
與WebSettings相關(guān)的C層結(jié)構(gòu)是struct
FieldIds,該結(jié)構(gòu)保存了WebSettings類中定義的屬性ID以及方法ID,在WebCore初始化時(shí)(WebViewCore的靜態(tài)方法中
使用System.loadLibrary載入)會(huì)設(shè)置這些方法和屬性的ID值。
6. WebView
與WebView相關(guān)的C層類是WebViewNative,該類中的mJavaGlue中保存了WebView中定義的屬性和方法ID,在
WebViewNative構(gòu)造方法中初始化,并且將構(gòu)造的WebViewNative對(duì)象的指針,賦值給WebView類的mNativeClass變
量,這樣WebView和WebViewNative對(duì)象就建立了關(guān)系。
3.2.2 主要類關(guān)系
與java層相關(guān)的C層類如下表所示:
ChromeClientAndroid |
該類主要處理WebCore中與Frame裝飾相關(guān)的操作。例如設(shè)置狀態(tài)欄、滾動(dòng)條、
Javascript腳本提示框等。當(dāng)瀏覽器中有關(guān)事件產(chǎn)生時(shí),ChromeClientAndroid類的相應(yīng)方法會(huì)被調(diào)用,該類會(huì)將相關(guān)的UI事件通
過(guò)Bridge傳遞給Java層,由Java層負(fù)責(zé)繪制以及用戶交互方面的處理。 |
EditorClientAndroid |
該類負(fù)責(zé)處理頁(yè)面中文本相關(guān)的處理,比如文本輸入、取消、輸入法數(shù)據(jù)處理、文本粘貼、文本編輯等操作。不過(guò)目前該類只對(duì)按鍵相關(guān)的事件進(jìn)行了處理,其他操作均未支持。 |
ContextMenuClient |
該類提供頁(yè)面相關(guān)的功能菜單。比如圖片拷貝、朗讀、查找等功能。但是,目前項(xiàng)目中未實(shí)現(xiàn)具體功能。 |
DragClient |
該類定義了與頁(yè)面拖拽相關(guān)的處理,但是目前該類沒(méi)有實(shí)現(xiàn)具體功能。 |
FrameLoaderClientAndroid |
該類提供與Frame加載相關(guān)的操作,當(dāng)用戶請(qǐng)求加載一個(gè)頁(yè)面時(shí),WebCore分析完網(wǎng)頁(yè)數(shù)據(jù)后,會(huì)通過(guò)該類調(diào)用Java層的回調(diào)方法,通知UI相關(guān)的組件處理。 |
InspectorClientAndroid |
該類提供與窗口相關(guān)的操作,比如窗口顯示、關(guān)閉窗口、附加窗口等。不過(guò)目前該類的各個(gè)方法均為空實(shí)現(xiàn)。 |
Page |
該類提供與頁(yè)面相關(guān)的操作,比如網(wǎng)頁(yè)頁(yè)面的前進(jìn)、后退等操作。 |
FrameBridge |
該類對(duì)Frame相關(guān)的Java層方法進(jìn)行了封裝,當(dāng)有Frame事件產(chǎn)生時(shí),WebCore通過(guò)FrameBridge回調(diào)Java的回調(diào)函數(shù),完成用戶交互過(guò)程。 |
AssetManager |
該類為瀏覽器提供本地資源訪問(wèn)功能。 |
RenderSkinAndroid |
該類與控件繪制相關(guān),所有的繪制控件類都需要從該類派生,目前WebKit模塊中有Button、Combo、Radio三類控件。 |
以上幾個(gè)類會(huì)在Java層請(qǐng)求創(chuàng)建WebFrame的時(shí)候被建立,他們的關(guān)系如下圖所示:
上圖中標(biāo)注為深綠色的FrameAndroid是瀏覽器Frame,一個(gè)BrowserFrame對(duì)象對(duì)應(yīng)著一個(gè)FrameAndroid對(duì)象。而
其他8個(gè)標(biāo)注為淡綠色的類,是與該Frame顯示、布局等相關(guān)的類。WebKit模塊中所有WebCore核心代碼與用戶交互的操作使用
FrameAndroid對(duì)象中的Briedge處理(回調(diào)相應(yīng)的Java方法)。
四、基本操作分析
4.1 WebKit模塊初始化
Android
SDK中提供了WebView類,該類為客戶提供客戶化瀏覽顯示的功能,如果客戶需要加入瀏覽器支持,可將該類的實(shí)例或者派生類的實(shí)例作為視圖,調(diào)用
Activity類的SetContentView顯示給用戶。當(dāng)客戶代碼中第一次生成WebView對(duì)象時(shí),會(huì)初始化WebKit庫(kù)(包括Java層和
C層兩個(gè)部分),之后用戶可以操作WebView對(duì)象完成網(wǎng)絡(luò)或者本地資源的訪問(wèn)。
WebView對(duì)象的生成主要涉及3個(gè)類CallbackProxy、WebViewCore以及WebViewDatabase。其中
CallbackProxy對(duì)象為WebKit模塊中UI線程和WebKit類庫(kù)提供交互功能,WebViewCore是WebKit的核心層,負(fù)責(zé)與C
層交互以及WebKit模塊C層類庫(kù)初始化,而WebViewDatabase為WebKit模塊運(yùn)行時(shí)緩存、數(shù)據(jù)存儲(chǔ)提供支持。WebKit模塊初始化
流程如下:
WebView
- +- 創(chuàng)建CallbackProxy對(duì)象
- +- 創(chuàng)建WebViewCore對(duì)象
- 調(diào)用System.loadLibrary載入webcore類相關(guān)庫(kù)(C層)
- 如果是第一次初始化WebViewCore對(duì)象,創(chuàng)建WebCoreThread線程
- 創(chuàng)建EventHub對(duì)象,處理WebViewCore事件
- 獲取WebIconDatabase對(duì)象實(shí)例
- 向WebCoreThread發(fā)送初始化消息
- +- 獲取WebViewDatabase實(shí)例
如上所述,第一步調(diào)用System.loadLIbrary方法載入webcore相關(guān)類庫(kù),該過(guò)程由Dalvik虛擬機(jī)完成,它會(huì)動(dòng)態(tài)從鏈接庫(kù)目錄中尋
找libWebCore.so類庫(kù),載入內(nèi)存中,并且調(diào)用WebKit初始化模塊的JNI_OnLoad方法。WebKit模塊的JNI_OnLoad方
法中完成如下初始化操作:
a) 初始化framebridge[register_android_webcore_framebridge]
初始化gFrameAndroidField靜態(tài)變量,以及注冊(cè)BrowserFrame類中的本地方法表。
b) 初始化javabridge[register_android_webcore_javabridge]
初始化gJavaBridge.mObject對(duì)象,以及注冊(cè)JWebCoreJavaBridge類中的本地方法
c) 初始化資源loader[register_android_webcore_resource_loader]
初始化gResourceLoader靜態(tài)變量,以及注冊(cè)LoadListener類的本地方法
d) 初始化webviewcore[register_android_webkit_webviewcore]
初始化gWebCoreViewImplField靜態(tài)變量,以及注冊(cè)WebViewCore類的本地方法
e) 初始化webhistory[register_android_webkit_webhistory]
初始化gWebHistoryItem結(jié)構(gòu),以及注冊(cè)WebBackForwardList和WebHistoryItem類的本地方法
f) 初始化webicondatabase[register_android_webkit_webicondatabase]
注冊(cè)WebIconDatabase類的本地方法
g) 初始化websettings[register_android_webkit_websettings]
初始化gFieldIds靜態(tài)變量,以及注冊(cè)WebSettings類的本地方法
h) 初始化webview[register_android_webkit_webview]
初始化gWebViewNativeField靜態(tài)變量,以及注冊(cè)WebView類的本地方法
第二步是WebCoreThread初始化,該初始化只在第一次創(chuàng)建WebViewCore對(duì)象時(shí)完成,當(dāng)用戶代碼第一次生成WebView對(duì)象,會(huì)在初
始化WebViewCore類時(shí)創(chuàng)建WebCoreThread線程,該線程負(fù)責(zé)處理WebCore初始化事件。此時(shí)WebViewCore構(gòu)造函數(shù)會(huì)被
阻塞,直到一個(gè)WebView初始化請(qǐng)求完畢時(shí),會(huì)在WebCoreThread線程中喚醒。
第三步創(chuàng)建EventStub對(duì)象,該對(duì)象處理WebView類的事件,當(dāng)WebCore初始化完成后會(huì)向WebView對(duì)象發(fā)送事件,WebView類的EventStub對(duì)象處理該事件,并且完成后續(xù)初始化工作。
第四步獲取WebIconDatabase對(duì)象實(shí)例。
第五步向WebViewCore發(fā)送INITIALIZE事件,并且將this指針作為消息內(nèi)容傳遞。WebView類主要負(fù)責(zé)處理UI相關(guān)的事件,而
WebViewCore主要負(fù)責(zé)與WebCore庫(kù)交互。在運(yùn)行時(shí)期,UI線程和WebCore數(shù)據(jù)處理線程是運(yùn)行在兩個(gè)獨(dú)立的線程當(dāng)中。
WebCoreThread線程接收到INITIALIZE線程后,會(huì)調(diào)用消息對(duì)象參數(shù)的initialize方法,而后喚醒阻塞的
WebViewCore
Java線程(該線程在WebViewCore的構(gòu)造函數(shù)中被阻塞)。不同的WebView對(duì)象實(shí)例有不同的WebViewCore對(duì)象實(shí)例,因此通過(guò)消
息的方式可以使得UI線程和WebViewCore線程解耦合。WebCoreThread的事件處理函數(shù),處理INITIALIZE消息時(shí),調(diào)用的是不
同WebView中WebViewCore實(shí)例的initialize方法。WebViewCore類中的initialize方法中會(huì)創(chuàng)建
BrowserFrame對(duì)象(該對(duì)象管理整個(gè)WEB窗體,以frame相關(guān)事件),并且向WebView對(duì)象發(fā)送
WEBCORE_INITIALIZED_MSG_ID消息。WebView消息處理函數(shù),會(huì)根據(jù)消息參數(shù)1初始化指定的WebViewCore對(duì)象,并
且更新WebViewCore的Frame緩沖。
初始化過(guò)程的序列圖如下圖所示:
初始化完成后Java層和C層類圖關(guān)系如下圖所示:
上圖中淡綠色的類表示Java層,而灰色類表示C層。
4.2 數(shù)據(jù)載入
4.2.1 載入網(wǎng)路數(shù)據(jù)
客戶代碼中可以使用WebView類的loadUrl方法,請(qǐng)求訪問(wèn)指定的URL網(wǎng)頁(yè)數(shù)據(jù)。WebView對(duì)象中保存著WebViewCore的引用,由
于WebView屬于UI線程,而WebViewCore屬于后臺(tái)線程,因此WebView對(duì)象的loadUrl被調(diào)用時(shí),會(huì)通過(guò)消息的方式將URL信息
傳遞給WebViewCore對(duì)象,該對(duì)象會(huì)調(diào)用成員變量mBrowserFrame的loadUrl方法,進(jìn)而調(diào)用WebKit庫(kù)完成數(shù)據(jù)的載入。其調(diào)
用函數(shù)序列如下所示:
網(wǎng)絡(luò)數(shù)據(jù)的載入分別由Java層和C層共同完成,Java層完成用戶交互、資源下載等操作,而C層主要完成數(shù)據(jù)分析(建立DOM樹(shù)、分析頁(yè)面元素等)操
作。由于UI線程和WebCore線程運(yùn)行在不同的兩個(gè)線程中,因此當(dāng)用戶請(qǐng)求訪問(wèn)網(wǎng)絡(luò)資源時(shí),通過(guò)消息的方式向WebViewCore對(duì)象發(fā)送載入資源
請(qǐng)求。在Java層的WebKit模塊中,所有與資源載入相關(guān)的操作都是由BrowserFrame類中對(duì)應(yīng)的方法完成,這些方法是本地方法,會(huì)直接調(diào)用
WebCore庫(kù)的C層函數(shù)完成數(shù)據(jù)載入請(qǐng)求,以及資源分析等操作。如上圖所示,C層的FrameLoader類是瀏覽框架的資源載入器,該類負(fù)責(zé)檢查訪
問(wèn)策略以及向Java層發(fā)送下載資源請(qǐng)求等功能。在FrameLoader中,當(dāng)用戶請(qǐng)求網(wǎng)絡(luò)資源時(shí),經(jīng)過(guò)一系列的策略檢查后會(huì)調(diào)用
FrameBridge的startLoadingResource方法,該方法會(huì)回調(diào)BrowserFrame(Java)類的
startLoadingResource方法,完成網(wǎng)絡(luò)數(shù)據(jù)的下載,而后BrowserFrame(Java)類的
startLoadingResource方法會(huì)返回一個(gè)LoadListener的對(duì)象,F(xiàn)rameLoader會(huì)刪除原有的FrameLoader對(duì)
象,將LoadListener對(duì)象封裝成ResourceLoadHandler對(duì)象,并且將其設(shè)置為新的FrameLoader。到此完成了一次資源
訪問(wèn)請(qǐng)求,接下來(lái)的任務(wù)即是WebCore庫(kù)會(huì)根據(jù)資源數(shù)據(jù)進(jìn)行分析和構(gòu)建DOM,以及相關(guān)的數(shù)據(jù)結(jié)構(gòu)。
4.2.2 載入本地?cái)?shù)據(jù)
本地?cái)?shù)據(jù)是以data://開(kāi)頭的URL表示,載入過(guò)程和網(wǎng)絡(luò)數(shù)據(jù)一樣,只不過(guò)在執(zhí)行FrameLoader類的executeLoad方法時(shí),會(huì)
根據(jù)URL的SCHEME類型區(qū)分,調(diào)用DataLoader的requestUrl方法(參看3.1.2.1節(jié)對(duì)載入器的分析),而不是調(diào)用
handleHTTPLoad建立實(shí)際的網(wǎng)絡(luò)通信連接。
4.2.3 載入文件數(shù)據(jù)
文件數(shù)據(jù)是以file://開(kāi)頭的URL,載入的基本流程與網(wǎng)絡(luò)數(shù)據(jù)載入流程基本一致,不同的是在運(yùn)行FrameLoader類的
executeLoad方法時(shí),根據(jù)SCHEME類型,調(diào)用FileLoader的requestUrl方法,完成數(shù)據(jù)加載(參看3.1.2.1節(jié)對(duì)載入
器的分析)。
4.3 刷新繪制
當(dāng)用戶拖動(dòng)滾動(dòng)條、有窗口遮蓋、或者有頁(yè)面事件觸發(fā)都會(huì)向WebViewCore(Java層)對(duì)象發(fā)送背景重繪消息,該消息會(huì)引起網(wǎng)頁(yè)數(shù)據(jù)的繪制操作。
WebKit的數(shù)據(jù)繪制可能出于效率上的考慮,沒(méi)有通過(guò)Java層,而是直接在C層使用SGL庫(kù)完成。與Java層圖形繪制相關(guān)的Java對(duì)象有如下幾
個(gè):
1. Picture類
該類對(duì)SGL封裝,其中變量mNativePicture實(shí)際上是保存著SkPicture對(duì)象的指針。WebViewCore中定義了兩個(gè)Picture對(duì)象,當(dāng)作雙緩沖處理,在調(diào)用webKitDraw方法時(shí),會(huì)交換兩個(gè)緩沖區(qū),加速刷新速度。
2. WebView類
該類接受用戶交互相關(guān)的操作,當(dāng)有滾屏、窗口遮蓋、用戶點(diǎn)擊頁(yè)面按鈕等相關(guān)操作時(shí),WebView對(duì)象會(huì)與之相關(guān)的WebViewCore
對(duì)象發(fā)送VIEW_SIZE_CHANGED消息。當(dāng)WebViewCore對(duì)象接收到該消息后,將構(gòu)建時(shí)建立的mContentPictureB刷新到
屏幕上,然后將mContentPictureA與之交換。
3. WebViewCore類
該類封裝了WebKit C層代碼,為視圖類提供對(duì)WebKit的操作接口,所有對(duì)WebKit庫(kù)的用戶請(qǐng)求均由該類處理,并且該類還為視圖類提供了兩個(gè)Picture對(duì)象,用于圖形數(shù)據(jù)刷新。
下面以Web頁(yè)面被鼠標(biāo)拖拽的情況為例子,分析網(wǎng)頁(yè)數(shù)據(jù)刷新過(guò)程。
當(dāng)用戶使用手指點(diǎn)擊觸摸屏,并且移動(dòng)手指,則會(huì)引發(fā)touch事件的產(chǎn)生,Android平臺(tái)會(huì)將touch事件傳遞給最前端的視圖相應(yīng)
(dispatchTouchEvent方法處理)。在WebView類中定義了5種touch模式,在手指拖動(dòng)Web頁(yè)面的情況下,會(huì)觸發(fā)
mMotionDragMode,并且會(huì)調(diào)用View類的scrollBy方法,觸發(fā)滾屏事件以及使視圖無(wú)效(重繪,會(huì)調(diào)用View的onDraw方
法)。WebView視圖中的滾屏事件由onScrollChanged方法響應(yīng),該方法向WebViewCore對(duì)象發(fā)送
SET_VISIBLE_RECT事件。
WebViewCore對(duì)象接收到SET_VISIBLE_RECT事件后,將消息參數(shù)中保存的新視圖的矩形區(qū)域大小傳遞給
nativeSetVisibleRect方法,通知WebCoreViewImpl對(duì)象(C層)視圖矩形變更
(WebCoreViewImpl::setVisibleRect方法)。在setVisibleRect方法中,會(huì)通過(guò)虛擬機(jī)調(diào)用
WebViewCore的contentInvalidate方法,該方法會(huì)引發(fā)webkitDraw方法的調(diào)用(通過(guò)WEBKIT_DRAW消息)。在
webkitDraw方法里,首先會(huì)將mContentPictureB對(duì)象傳遞給本地方法nativeDraw繪制,而后將
mContentPictureB的內(nèi)容與mContentPictureA的內(nèi)容對(duì)調(diào)。在這里mContentPictureA
緩沖區(qū)是供給WebViewCore的draw方法使用,如果用戶選擇某個(gè)控件,繪制焦點(diǎn)框時(shí)候WebViewCore對(duì)象的draw方法會(huì)調(diào)用,繪制的
內(nèi)容保存在mContentPictureA中,之后會(huì)通過(guò)Canvas對(duì)象(Java層)的drawPicture方法將其繪制到屏幕上,而
mContentPictureB緩沖區(qū)是用于built操作的,nativeDraw方法中首先會(huì)將傳遞的mContentPictureB對(duì)象數(shù)據(jù)重
置,而后在重新構(gòu)建的mContentPictureB畫(huà)布上,將層上相關(guān)的元素繪制到該畫(huà)布上。上面提到,之后會(huì)將mContentPictureB和
mContentPictureA的內(nèi)容對(duì)調(diào),這樣一次重繪事件產(chǎn)生時(shí)(會(huì)調(diào)用WebView.onDraw方法)會(huì)將mContentPictureA
的數(shù)據(jù)使用Canvas類的drawPicture繪制到屏幕上。當(dāng)webkitDraw方法將mContentPictureA與
mContentPictureB指針對(duì)調(diào)后,會(huì)向WebView對(duì)象發(fā)送NEW_PICTURE_MSG_ID消息,該消息會(huì)引發(fā)
WebViewCore的VIEW_SIZE_CHANGED消息的產(chǎn)生,并且會(huì)使當(dāng)前視圖無(wú)效產(chǎn)生重繪事件(invalidate()),引發(fā)
onDraw方法的調(diào)用,完成一次網(wǎng)頁(yè)數(shù)據(jù)的繪制過(guò)程。
~~~ END ~~~
本文轉(zhuǎn)自: http://www.jjos.org/android/2010/05/10/312_webkit-webkit-for-android.html