• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            xiaoguozi's Blog
            Pay it forword - 我并不覺的自豪,我所嘗試的事情都失敗了······習慣原本生活的人不容易改變,就算現狀很糟,他們也很難改變,在過程中,他們還是放棄了······他們一放棄,大家就都是輸家······讓愛傳出去,很困難,也無法預料,人們需要更細心的觀察別人,要隨時注意才能保護別人,因為他們未必知道自己要什么·····

            瀏覽器探究——執行網頁跳轉

            Main線程中執行。

            UrlInputView

            控件UrlInputView執行OnEditorAction->finishInput

            /**

             *url/search input view

             *handling suggestions

             */

            public class UrlInputView extendsAutoCompleteTextView

                   implements OnEditorActionListener,

                   CompletionListener, OnItemClickListener, TextWatcher

            由此可見,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.

            http://blog.csdn.net/hxwwf/article/details/7281318
            posted on 2013-02-22 15:07 小果子 閱讀(1647) 評論(0)  編輯 收藏 引用 所屬分類: 學習筆記Android & Ios
            国内精品久久久久久中文字幕| 久久精品人人做人人爽电影| 国产精品久久午夜夜伦鲁鲁| 国产精品久久国产精品99盘| 99久久夜色精品国产网站| 国产91久久综合| 亚洲午夜久久久久久久久久| 久久天天躁狠狠躁夜夜网站| 精品久久久久久无码免费| 中文精品99久久国产 | 久久一区二区三区99| 中文精品久久久久人妻不卡| 一级做a爱片久久毛片| 成人午夜精品无码区久久| 91秦先生久久久久久久| 亚洲中文字幕无码久久2017 | 狠狠色丁香婷综合久久| 午夜视频久久久久一区| 99久久精品影院老鸭窝| 久久久久久久久久久精品尤物| a高清免费毛片久久| 亚洲AV乱码久久精品蜜桃| 久久午夜综合久久| 国产激情久久久久影院老熟女免费| 精品无码久久久久国产动漫3d| 国产99久久久国产精品~~牛 | 亚洲色欲久久久综合网| 欧美成a人片免费看久久| 国产精品成人久久久久三级午夜电影 | 久久精品无码专区免费青青| 久久久久人妻一区精品| 99久久精品国产一区二区三区| 国内精品久久久久影院一蜜桃 | 久久人做人爽一区二区三区| 久久精品视屏| 国产精品免费久久久久电影网| 91久久精一区二区三区大全| 久久亚洲AV成人无码电影| 久久久久亚洲Av无码专| 久久综合国产乱子伦精品免费| 日产精品99久久久久久|