Main線程中執行。 java
UrlInputView android
控件UrlInputView執行OnEditorAction->finishInput web
/** 瀏覽器
*url/search input view 網絡
*handling suggestions dom
*/ 函數
public class UrlInputView extendsAutoCompleteTextView post
implements OnEditorActionListener, this
CompletionListener, OnItemClickListener, TextWatcher url
因而可知,UrlInputView即輸入網址的那個控件,該控件包括輸入URL和執行搜索輸入。
Controller
在通過UrlInputView的處理後,會調用Controller.handleNewIntent。
Controller是瀏覽器中最重要的類,做爲整個瀏覽器的主控類。Controller中有IntentHandler,這裏會調用IntentHandler.onNewIntent
IntentHandler
//Handle all browser related intents
這裏對一些特殊的URL作處理這裏還包含了一些debug信息,好比」about:debug.dom.file"這種形式的網址。若是是普通的url,不須要作特殊處理,則執行到最後執行Controller.loadUrlDataIn,即通過了IntentHandler後又回到了Controller。
Controller
/**
* Load UrlData into a Tab and update the title bar to reflect the new
* load. Call this instead ofUrlData.loadIn directly.
* @param t The Tab used to load.
* @param data The UrlData being loaded.
*/
通過簡單的處理,會把要加載的url做爲參數調用被顯示的tab,即執行Tab.loadUrl。這樣看來Controller還只是個橋樑的做用,把從UrlInputView獲得的url,交給IntentHandler作處理,而後再把url交給Tab作實際的加載。
Tab
//Class for maintaining Tabs with a mainWebView and a subwindow.
Tab做爲一個窗口的抽象概念而存在,對一個窗口的操做都須要經過Tab來進入。另外有個TabControl用來管理全部的Tab.
執行語句mMainView.loadUrl。這個mMainView是個WebView。從這終於進入了framework的webkit層了。
WebView
WebView做爲Tab的核心控件,負責網頁的真正的加載,顯示等操做,是framework/webkit中最主要的類。經過Tab來找到WebView.
在WebView.loadUrl->WebView.loadUrlImpl中會向WebViewCore發消息,
WebViewCore
該類在一個獨立的線程中運行,該類主要經過Message,Handler的機制在WebView與WebViewCore之間通信的,這裏WebView是在Main線程中,而WebViewCore是在單獨的 WebViewCoreThread線程中。WebViewCore是framework/webkit核心類,它在單獨的線程中來接收消息,每一個消息至關於一個請求的任務,而這個WebViewCore至關於一個服務,它在消息循環中不停的接收任務(消息),而後處理任務,而後再接收下一個任務(消息)。任務的執行不少是經過jni調用c層webkit來操做的。在c層webkit有webkit/Source/WebKit/android/jni/WebViewCore.cpp與該java層的WebViewCore對應。即這個WebViewCore是java層與c層的一個主要橋樑。
在WebView.loadUrlImpl在執行了mWebViewCore.sendMessage(EventHub.LOAD_URL, arg);則WebViewCore接收到LOAD_URL任務,執行對它的處理。
WebViewCore中有BrowserFrame成員
BrowserFrame
BrowserFrame extends Handler它也有不少JNI與C層的webkit的Webkit/Source/WebKit/android/jni/WebCoreFrameBridge.cpp對應。它用來處理頁面的具體狀況,即Frame,這個Frame是一個具體的頁面的概念。
WebViewCore.loadUrl會調用BrowserFrame.loadUrl。BrowserFrame會調用到WebCoreFrameBridge.cpp的LoadUrl。
這裏略去c層的處理部分。
WebCoreFrameBridge.cpp的LoadUrl執行後會執行到WebCoreFrameBridge.cpp的loadStarted,這裏又會回調BrowserFrame.loadStarted函數。
/**
* native callback
* Indicates the beginning of a new load.
* This method will be called once for the main frame.
*/
即經過BrowserFrame的loadUrl在c層作處理後,又回調到BrowserFrame的loadStarted。
這裏在理一下,主線程中有Tab,Tab裏有WebView。即WebView也是運行在主線程的。而WebView裏有WebViewCore,WebViewCore又是運行在一個單獨的線程裏的。
那麼多個WebView是否就對應多個WebViewCore和多個WebViewCore線程呢?
看下WebView,WebView的構造函數中會mWebViewCore= new WebViewCore(context, this, mCallbackProxy, javaScriptInterfaces);建立了WebViewCore對象,即每一個WebView都有個WebViewCore對象。可是WebViewCore中的WebCoreThread是一個靜態的,即一個單例的。而這個WebCoreThread中運行的privatestatic Handler sWebCoreHandler;也是個靜態的。
因而可知WebViewCore類自己就是個外殼,真正處理任務的是WebCoreThread及其裏面的sWebCoreHandler,這個真正處理任務的是靜態的,只有一份,WebViewCore這個外殼只是溝通webView與WebCoreThread的橋樑,至關於一個代理類。是WebCoreThread提供給外面的處理接口。
那麼BrowserFrame呢?在WebViewCore的構造最後會發送一個INITIALIZE的消息給WebCoreThread,WebCoreThread接收到後會執行WebViewCore.initialize,這個函數會構造mrowserFrame。即每次構造WebViewCore時一樣會構造一個BrowserFrame。可是爲何不在主線程中建立呢?一方面它是繼承自Handler,這個Handler須要在WebViewCoreThread線程中運行,因此須要在該線程來建立。另外一方面在它的構造中須要建立JWebCoreJavaBridge這個是C層的類,貌似這個類也須要在WebViewCoreThread線程中建立和銷燬才行。
由上分析可知,WebView包含一個WebViewCore,WebViewCore包含一個BrowserFrame。多個WebViewCore共同對應惟一的一個WebCoreThread。WebViewCore只是個外殼,WebCoreThread做爲任務的處理,WebCoreThread主要就是個大Handler不停的處理接收到的任務,WebCoreThread會調用不少jni來調用webkit接口,BrowserFrame也有不少jni來調用webkit接口。由他們的組成狀況又可知WebCoreThread直接調的jni是多個WebView共同的,即不跟具體的WebView相關,而經過BrowserFrame調用的則跟一個具體的WebView相關了。
CallBackProxy
/**
*This class is a proxy class for handling WebCore -> UI thread messaging. All
*the callback functions are called from the WebCore thread and messages are
*posted to the UI thread for the actual client callback.
*/
/*
*This class is created in the UI thread so its handler and any private classes
*that extend Handler will operate in the UI thread.
*/
class CallbackProxy extends Handler {
另外還有個類CallBackProxy。它存在於WebView,WebViewCore,BrowserFrame中。在WebView構造函數中建立,並在WebViewCore和BrowserFrame構造函數中做爲參數傳入並賦值給它們內部的引用。可見CallBackProxy是WebViewCore和BrowserFrame向WebView回調的橋樑。
CallBackProxy是一個Handler,它在主線程中被建立,即WebViewCore和BrowserFrame會經過發消息的方式將需求傳遞到主線程的CallBackProxy中,CallBackProxy的事件處理循環會執行相應的處理。可見主線程中WebView經過WebViewCore發消息給WebViewCoreThread線程執行操做,WebViewCoreThread線程又會經過CallBackProxy回調消息給主線程執行處理。
再回到BrowserFrame.loadStarted處。
BrowserFrame.loadStarted會調用CallBackProxy.onPageStarted,CallBackProxy.onPageStarted中會給發PAGE_STARTED消息,主線程中的CallBackProxy的handleMessage會執行處理。在處理時會執行WebViewClient.onPageStarted。
WebViewClient
mWebViewClient自己只是提供一個接口基類,Tab中private finalWebViewClient mWebViewClient = new WebViewClient()
// WebViewClient implementation for themain WebView
//Set the WebViewClient that will receivevarious notifications and requests. This will replace the current handler.
這個WebViewClient會傳給Tab中的WebView的CallbackProxy。這個WebViewClient會讓CallbackProxy返回信息或回調處理給Tab。
回到WebViewClient.onPageStarted,這裏作了一些判斷處理後,調用WebViewController.onPageStarted。
WebViewController
//WebView aspect of the controller
public interface WebViewController
在Tab的構造時,WebViewController會做爲參數傳入,並設置給Tab。那麼Tab中的WebViewController究竟是什麼?Tab是在TabController中建立的,而Tab構造時傳入的是Controller。
public class Controller implementsWebViewController, UiController
因而可知Tab中的WebViewController其實就是對應Controller。只是經過WebViewController接口做爲引用的。即Tab中只關心Controller的WebViewController接口部分。
這樣就能夠看出BrowserFrame經過消息與主線程中的CallbackProxy處理循環關聯,CallbackProxy又經過WebViewClient與Tab關聯,回調了Tab提供的接口,而Tab又經過WebViewController接口,調用了Controller這個核心類的函數。即調用到WebViewController.onPageStarted,也便是Controller.onPageStarted.
Controller.onPageStarted中一個主要的處理是
if (!mNetworkHandler.isNetworkUp()) { view.setNetworkAvailable(false); }這裏判斷網絡是不是激活狀態,若是不是激活狀態則執行WebView.SetNetworkAvailable(Boolean networkUp)
/** * Inform WebView ofthe network state. This is used to set * the JavaScript property window.navigator.isOnline and * generates the online/offline event asspecified in HTML5, sec. 5.7.7 *@param networkUp boolean indicating if network is available */
該函數其實就是像WebViewCore發送SET_NETWORK_STATE消息,好吧,又回到了WebViewCoreThread線程了,處理的方式是直接BrowserFrame.sJavaBridge.setNetworkOnLine。這個函數是個jni函數,其調用的是c層JavaBridge的函數。這個jni函數主要就是通知c層WebCore網路狀態已經變化,並把最新的網絡狀態告訴WebCore。
因而可知WebView.setNetworkAvailable仍是個挺重要的函數,經過它才能告訴底層網絡的狀態。
那麼額外看下網絡狀態如何獲取並傳遞的,在loadUrl發起加載url這塊判斷了一次,即當無網絡時主動通知一次。其餘的呢?
在NetworkStateHandler中會註冊一個BroadcastReceiver,該receiver會關注ConnectivityManager.CONNECTIVITY_ACTION廣播,該廣播是在網絡發生鏈接變化時被髮出,該receiver在接收到網絡鏈接變化的廣播後,會查詢當前的鏈接狀況,而後執行NetworkStarteHandler.onNetworkToggle,這個函數裏面就會調用WebView.setNetworkAvailable,也即跟上述描述的那樣,給WebViewCoreThread線程發消息,通知c層WebCore網絡的最新狀態。
這樣就清楚了,網絡廣播時會通知C層最新狀態,在執行loadUrl時,若是網絡不可用也會通知C層網絡最新狀態。
這裏先跨過Controller.onPageStarte的其餘處理過程。這次任務處理完畢。
此時WebViewCoreThread線程中BrowserFrame仍然處於c層的LoadUrl中,此時的調用棧爲:
BrowserFrame.nativeLoadUrl
BrowserFrame.loadUrl
WebViewCore.loadUrl
這裏又會回調BrowserFrame.shouldInterceptRequest,它會調用BrowserFrame.inputStreamForAndroidResource函數
/**
* Get the InputStream for an Android resource
* There are three different kinds of android resources:
* - file:///android_res
* - file:///android_asset
* - content://
* @param url The url to load.
* @return An InputStream to the android resource
*/
這個函數會對幾種特殊的url作不一樣的處理,當輸入一個標準的http的url時,該函數不起什麼做用。
BrowserFrame.shouldInterceptReques接下來會調用CallbackProxy.shouldInterceptRequest,看到調用CallbackProxy的函數,基本上就是要發消息給主線程讓主線程去處理任務了,這裏發送了LOAD_RESOURCE消息,主線程接收後執行WebViewClient.onLoadResource。回到BrowserFrame.nativeLoadUrl處,此時這個jni的函數終於執行完畢,也再也不回調其餘函數了,該函數完成,WebViewCoreThread線程執行完LoadUrl的處理。
當沒有鏈接網絡時,有個單獨的線程會執行JWebCoreJavaBridge.signalServiceFuncPtrQueue這個JNI的回調函數,該回調函數會發FYBCPTR_MESSAGE消息給WebViewCoreThread線程,但處理函數是JWebCoreJavaBridge.handle,因而可知WebViewCoreThread線程不只僅有一個Handler在處理事件.
JWebCoreJavaBridge
JWebCoreJavaBridge extends Handler 可見JWebCoreJavaBridge也是個Handler也是在WebViewCoreThread線程中運行的,只是發送消息的線程不是主線程,是另外一個單獨的線程,而且消息的發送來源是JNI的回調。
JWebCoreJavaBridge對應的JNI是webkit/Source/WebKit/android/jni/JavaBridge.cpp的函數。
JWebCoreJavaBridge處理FYBCPTR_MESSAGE消息時會調用一個JNI函數,在JNI函數裏又會回調BrowserFrame.reportError。
又是跟上面相似的流程,BrowserFrame.reportError調用CallbackProxy.onReceiveError,這個CallbackProxy裏會發消息REPORT_ERROR,而後主線程接收消息,執行WebViewClient.onReceivedError。
接着又是收到FUNCPTR_MESSAGE消息,調用nativeServiceFuncPtrQueue,可是這裏回調了BrowserFrame.loadStarted,而後的處理流程跟上述的LoadUrl中調用BrowserFrame.loadStarted過程同樣。
接着WebViewCoreThread線程又是收到FUNCPTR_MESSAGE消息,調用JWebCoreJavaBridge.nativeServiceFuncPtrQueue,WebViewCore.contentDraw被調用,該函數發送WEBKIT_DRAW,處理該消息會執行繪製的操做。
接着WebViewCoreThread線程中JWebCoreJavaBridge.handleMessage又被調用,仍是FUNCPTR_MESSAGE消息,仍然是調用nativeServiceFuncPtrQueue。但此時BrowserFrame收到loadFinished的回調,發PAGE_FINISHED消息,主線程接收消息處理時會執行WebView.onPageFinished和WebViewClient.onFinished.