【转载】Android -- browser java 部分

本文是转载过来的,原文地址 http://blog.csdn.net/baimy1985/article/details/8482903

  本文主要对browser 的java部分代码一个简单说明,主线基本上围绕着第一次打开 browser加载网页的流程展开, 同时顺便提了下App层几个主要类的关系。以便大家可以更快了解 browser的上层代码,然后腾出时间去关注 webkit部分代码。webkit部分代码可非常多哦。首先根据logcat 的日志信息或 brower应用的Androidmanifest.xml, 打开browser 第一个界面是 BrowserActivity.java。这里面代码不多,关注下 oncreate()里初始化动作就好了,同时在这里我们也先整理下一些类的关系。

[java]  view plain copy
  1. public void onCreate(Bundle icicle) {       
  2.        super.onCreate(icicle);      
  3.        if (IntentHandler.handleWebSearchIntent(thisnull, getIntent())) {  
  4.            finish();  
  5.            return;  
  6.        }  
  7.        mController = new Controller(this, icicle == null);  
  8.        boolean xlarge = isTablet(this);  
  9.        if (xlarge) {  
  10.            mUi = new XLargeUi(this, mController);  
  11.        } else {  
  12.            mUi = new PhoneUi(this, mController);  
  13.        }  
  14.        mController.setUi(mUi);  
  15.        Bundle state = getIntent().getBundleExtra(EXTRA_STATE);  
  16.        if (state != null && icicle == null) {  
  17.            icicle = state;  
  18.        }  
  19.        mController.start(icicle, getIntent());     
        上面的代码做了下面几件事: 1、 New了一个controller 对象,

                                                             2、根据当前设备是 phone还是pad 初始化了 I, 

                                                              3. 把mUI传给 mController,让Controller 持有UI的引用以便后面可以操作 UI。

         再稍微往下看两步,看看 controller和UI 里面有什么。Controller的构造函数 :

[java]  view plain copy
  1.  public Controller(Activity browser, boolean preloadCrashState) {  
  2.        mActivity = browser;  
  3.        mSettings = BrowserSettings.getInstance();  
  4.        mTabControl = new TabControl(this);  
  5.        mSettings.setController(this);  
  6.       ……….省略了无关代码    
  7.        mFactory = new BrowserWebViewFactory(browser);  
  8.        ……..省略了无关代码    
  9. }  
        这里有一个 Tabcontrol,用来管理Tab ,这个Tab是什么呢?这要看下前面 UI这个接口的实现了,UI接口的实现类是 BaseUI,phoneUI 和XlargerUI均继承于 BaseUI(这里是典型的面向对象设计 )。BaseUI 由Titlebar和 Tab两部分组成,Titlebar就是我们看到网址输入那部分,而 Tab就是下面的网页部分,在 Tab.java的代码中,我们是可以找到 webview对象的,可以理解为Tab把 webview包装了一层。再回到controller这个类,注意 controller是实现了webviewCotroller ,UiController接口的(注意tabcontroller可不是接口,它只是一个普通类),到这里有没有感觉 controller.java这个类好强大,借助Tabcontroller管理着一组 Tab,Tab 有webview的实例, controller再根据具体的Tab对象控制着每一个 webview。这家伙就是browser app层的一个总管啊,只要能获得 controller的引用,就可以完成界面 webview的控制。 类的关系先说到这,下面还是看打开网页的流程吧,接 OnCeate()里面mController.start(icicle, getIntent());  具体的代码如下

[java]  view plain copy
  1. void start(final Bundle icicle, final Intent intent) {  
  2.        boolean noCrashRecovery = intent.getBooleanExtra(NO_CRASH_RECOVERY, false);  
  3.        if (icicle != null || noCrashRecovery) {  
  4.            doStart(icicle, intent, false);  
  5.        } else {  
  6.            mCrashRecoveryHandler.startRecovery(intent);  
  7.        }  
  8.    }  
       不管走哪个分支,最后还是会来到同一个类中的 doStart(final Bundle icicle, final Intent intent, final boolean fromCrash),在 doStart()里面的代码是我们关心的。 
[java]  view plain copy
  1. GoogleAccountLogin.startLoginIfNeeded(mActivity,  
  2. new Runnable() {  
  3.      @Override public void run() {  
  4.      onPreloginFinished(icicle, intent, currentTabId, restoreIncognitoTabs,  
  5.                                 fromCrash);  }  });    
      这里开一个线程去开始load网页内容,线程 start动作在startLoginIfNeeded ()这里面。去 onPreloginFinished里面看看吧,       

[java]  view plain copy
  1. private void onPreloginFinished(Bundle icicle, Intent intent, long currentTabId,  
  2.             boolean restoreIncognitoTabs, boolean fromCrash) {  
  3.         //省略了暂时无关的代码  
  4.         if (currentTabId == -1) {           
  5.             Tab t = null;  
  6.           if (urlData.isEmpty()) {  
  7.                 t = openTabToHomePage();// 没有url就打开主页  
  8.           } else {  
  9.                 t = openTab(urlData);// 打开传过来的 url  
  10.           }           
  11.         } else {  
  12.         }   
  13.     }  
        顺着上面的代码跟踪几步就会发现后面的流程大同小异,不管是 openTabToHomePage还是openTab ,都会执行 createNewTab(),再执行loadUrl() 函数,而 loadUrl()最终起作用代码在Tab.java,下面的代码
[java]  view plain copy
  1. public void loadUrl(String url, Map<String, String> headers) {  
  2.     if (mMainView != null) {  
  3.         mPageLoadProgress = INITIAL_PROGRESS;  
  4.         mInPageLoad = true;  
  5.         mCurrentState = new PageState(mContext, false, url, null);  
  6.         mWebViewController.onPageStarted(this, mMainView, null);  
  7.         mMainView.loadUrl(url, headers);  
  8.     }  
  9. }  
       mMainView是 webview的实例,所以到这里packages层的代码流程也就结束了,开始转入 framework层,毫无疑问webview.java肯定是这一层的核心的代码之一了。 来看看看Webview里的loadUrl ()方法。

[java]  view plain copy
  1. public void loadUrl(String url, Map<String, String> additionalHttpHeaders) {  
  2.     checkThread();  
  3.     loadUrlImpl(url, additionalHttpHeaders);  
  4. }  
  5.   
  6. private void loadUrlImpl(String url, Map<String, String> extraHeaders) {  
  7.     switchOutDrawHistory();  
  8.     WebViewCore.GetUrlData arg = new WebViewCore.GetUrlData();  
  9.     arg.mUrl = url;  
  10.     arg.mExtraHeaders = extraHeaders;  
  11.     mWebViewCore.sendMessage(EventHub.LOAD_URL, arg);// 要注意这个 TAG。  
  12.     clearHelpers();  
  13. }  
        通过对上面TAG :EventHub.LOAD_URL的跟踪,可以发现代码已经来到 WebCoreView
[java]  view plain copy
  1. case LOAD_URL: {  
  2.      CookieManager.getInstance().waitForCookieOperationsToComplete();  
  3.      GetUrlData param = (GetUrlData) msg.obj;  
  4.      loadUrl(param.mUrl, param.mExtraHeaders);  
  5.      break;  
  6. }  
        那这里的loadUrl() 指向哪里呢,继续看很快可以找到,借助IDE工具理清这样的关系还是很快的。
[java]  view plain copy
  1. private void loadUrl(String url, Map<String, String> extraHeaders) {  
  2.     if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, " CORE loadUrl " + url);  
  3.     mBrowserFrame.loadUrl(url, extraHeaders);  
  4. }  
        又出来个新变量mBrowserFrame,看下类型声明知道它是 BrowserFrame的实例,利用sourceInsight的跳转功能直接过去看看。

[java]  view plain copy
  1. public void loadUrl(String url, Map<String, String> extraHeaders) {  
  2.     mLoadInitFromJava = true;  
  3.     if (URLUtil.isJavaScriptUrl(url)) {  
  4.            stringByEvaluatingJavaScriptFromString(  
  5.                 url.substring("javascript:".length()));  
  6.     } else {  
  7.         nativeLoadUrl(url, extraHeaders);  
  8.     }  
  9.     mLoadInitFromJava = false;  
  10. }  
       这里看到nativeLoadUrl ,看来要用到 JNI的知识了,下面这句话告诉我们接下来去哪,

[java]  view plain copy
  1. "nativeLoadUrl""(Ljava/lang/String;Ljava/util/Map;)V", (void*) LoadUrl },  
       WebCoreFrameBridge.cpp (external\webkit\source\webkit\android\jni)里的loadUrl 函数,到这里算是把请求送 c层的webkit 了,目前也只跟到这里,后面就是等回调消息,除了前面提到的类还会涉及到 CallBackproxy.java,这个家伙是一个非常重要的桥梁,我们的 BrowserFrame会通过CallbackProxy 向主线程发消息,总之它是比较重要的,对于webkit部分的代码理解目前还处在迷糊状态,不知道从哪里下手,所以这后面流程还有待进一步挖掘,同时求高手指点一二。

        那么到这里小结一下,对 framework层的browser ,我们要重点关注 webview.java、CallBackproxy.java 、BrowserFrame.java、 WebCoreFrameBridge这几个类,其它类暂时还没注意到,肯定还有漏网之鱼,不过先把这几个主线类抓住再说,细节的东西慢慢来。

       本文的故事也到此结束,要说明的上面的只是对android原生浏览器 java部分代码调用流程的简单分析,事实上应用层代码功能更偏向对网页( webview)的管理和显示,与webkit本身没有太多的联系,如果只是对 webkit感兴趣,只看下webkit部分是完全可以的,当然它的代码规模还比较大,要花些时间去理解。


       PS:在目前的 browser设置中有个实验室选项,那个有快速控制选项,打开它会开启圆形的菜单功能,好像从android 3.0的版本开始就这个功能了,对应的代码实现是以 Pie开头的那些类代码,这个应该算是个动态控制的,不是固定坐标那种,有兴趣的可以看看

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值