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.