1. 程式人生 > >Cordova-android系列原始碼解讀(一)載入h5頁面流程

Cordova-android系列原始碼解讀(一)載入h5頁面流程

Cordova是一個比較成熟的跨跨平臺框架,核心思想就是Native提供h5容器,業務邏輯由h5處理,因為h5是直接跑在瀏覽器中的,既而達到跨平臺目的

  • 本文旨在梳理cordovar第一個流程,在android平臺載入h5過程。
    先放出目的:載入h5是通過WebView.loadUrl控制元件實現的
    Demo原始碼:
package com.mydomain.hello;

import android.os.Bundle;
import org.apache.cordova.*;

public class MainActivity extends CordovaActivity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        // enable Cordova apps to be started in the background
        Bundle extras = getIntent().getExtras();
        if (extras != null && extras.getBoolean("cdvStartInBackground", false)) {
            moveTaskToBack(true);
        }

        // Set by <content src="index.html" /> in config.xml
        loadUrl(launchUrl);
    }
}

loadUrl(launchUrl) 是由父類實現的,下面就依據這條線索依次分析,載入h5頁面涉及到的核心類如下:
CordovaActivity

  • 本類擴充套件於普通的Activity用來管理真正裝填h5頁面的那個Activity的生命週期,因為它是一個基類,主要處理一些共性行為,再載入h5頁面過程有如下幾個介面特別重要
  • public void loadUrl(String url) 介面目的較為明顯,載入h5的檔案地址,跟進原始碼會發現基類中這個介面併為實現h5的載入,而是通過CordovaWebView 的實現類CordovaWebViewImpl進行的,這裡有幾點程式碼設計上的規範值得我們學習:
    先抽一個公共的介面,約束一個物件的所有行為,具體做什麼由他的實現類去做,有點類似建房子的味道,介面好比一個設計圖,至於把這個建築物裝修成什麼風格,那就任由個人口味了。

CordovaWebView 的原始碼如下:

  • 介面命名很規範,大神的程式碼就是好懂,一看就大概知道是什麼意思,這也是俺這麼多年來一直追求的一個境界,這裡只放幾個核心的介面,其他的就不放了,大概從這幾方面進行定義的,初始化webView物件,回傳資料給js,管理webview的行為(暫停,停止,開始,清除webview中cache等,這裡就不一一例舉了)
    這裡寫圖片描述
    這裡寫圖片描述

CordovaWebViewImpl 的原始碼分析:
在CordovaWebView類註釋上知道,這個類是對其的實現:這裡寫圖片描述
看看這個類本身的註釋:
這裡寫圖片描述
可以知道這個類主要乾了這幾件事:

  • webView的互動
  • 管理與js互動的外掛,事件與一個CordovaWebViewEngine物件
  • 載入h5核心介面是loadUrlIntoView,這個介面主要做了這幾件事,詳細風截圖:
    這裡寫圖片描述
    這裡引出了一個engine物件,追蹤發現,這個物件是由物件這個物件時,傳進來的:
    這裡寫圖片描述

新物件SystemWebViewEngine

  • 本物件實現CordovaWebViewEngine所有介面,直奔主題:
    這裡寫圖片描述
    終於找到了最終載入h5頁面的物件,SystemWebView,而這個物件是擴充套件於 WebView的

小結:

  • 在演示類MainActivity直接呼叫loadUrl函式,因為MainActivity是擴充套件Cordovar而來的,而自己並未實現loadUrl這個函式介面,所以它呼叫的是Cordovar中的loadUrl介面。
  • 在CordovarActivity中 onCreate生命週期中主要先進行了一些基本配置,同時loadUrl函式介面呼叫了一次init操作,init內部邏輯主要進行3個動作,其一,建立CodovarWebView例項物件(呼叫makeWebView),檢視原始碼得知這個CordovarWebView為一個介面類,並不能直接進行例項化,在makeWebView函式介面內部可以得知實際建立的例項為CordovarWebViewImpl例項物件,在構建CordovarWebViewImpl例項物件時,它的構造器引數是一個CordovarWebViewEngin物件(但這個物件為一個介面類),而在這個構造器內部,它真正建立的是反射例項SysWebViewEngin物件。
  • 那麼CordovarActivity中loadUrl實際上走的appView.loadUrl而真正進行loadUrl是走SystemWebViewEngin中的WebView進行的