1. 程式人生 > >Cordova原始碼深入分析-第四講

Cordova原始碼深入分析-第四講

前面把外掛在js端的初始化,與js->Native->js端的通訊都介紹了一下

本章介紹一下,在native端的外掛初始化流程

在介紹所有的之前,我想先上一段程式碼(外掛配置):

<?xml version='1.0' encoding='utf-8'?>
<widget id="io.cordova.hellocordova" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <feature name="Whitelist">
        <param name="android-package" value="org.apache.cordova.whitelist.WhitelistPlugin" />
        <param name="onload" value="true" />
    </feature>
    <feature name="Camera">
        <param name="android-package" value="org.apache.cordova.camera.CameraLauncher" />
    </feature>
    <feature name="SMS">
        <param name="android-package" value="com.rjfun.cordova.sms.SMSPlugin" />
    </feature>
    <feature name="Notification">
        <param name="android-package" value="org.apache.cordova.dialogs.Notification" />
    </feature>
    <name>HelloCordova</name>
    <description>
        A sample Apache Cordova application that responds to the deviceready event.
    </description>
    <author email="
[email protected]
" href="http://cordova.io"> Apache Cordova Team </author> <content src="index.html" /> <access origin="*" /> <allow-intent href="http://*/*" /> <allow-intent href="https://*/*" /> <allow-intent href="tel:*" /> <allow-intent href="sms:*" /> <allow-intent href="mailto:*" /> <allow-intent href="geo:*" /> <allow-intent href="market:*" /> <preference name="loglevel" value="DEBUG" /> </widget>

還是從Activity的onCrete開始分析,首先呼叫的是CordovaActivity.java的loadUrl

程式碼段:1

    public void loadUrl(String url) {
        if (appView == null) {
            init(); //第一次肯定需要初始化 跳轉到程式碼段2
        }

        // If keepRunning
        this.keepRunning = preferences.getBoolean("KeepRunning", true);

        appView.loadUrlIntoView(url, true);
    }
程式碼段2:
    protected void init() {
        appView = makeWebView();//構建整個架構框架,程式碼段3
        createViews(); //建立view的地方,沒有太多邏輯,不關注了
        if (!appView.isInitialized()) {
            appView.init(cordovaInterface, pluginEntries, preferences);//這裡是重點,程式碼段4
        }
        cordovaInterface.onCordovaInit(appView.getPluginManager());

        // Wire the hardware volume controls to control media if desired.
        String volumePref = preferences.getString("DefaultVolumeStream", "");
        if ("media".equals(volumePref.toLowerCase(Locale.ENGLISH))) {
            setVolumeControlStream(AudioManager.STREAM_MUSIC);
        }
    }

程式碼段3:

    protected CordovaWebView makeWebView() {
        return new CordovaWebViewImpl(makeWebViewEngine());
    }
這裡涉及到兩個類,CordovaWebViewImpl 和  SystemWebViewEngine

engine是整個架構和核心的幹活的類,所有WebView的設定和操作都在這裡實現

Impl則是整個架構的核心管理模組,負責協調各個功能之間的互動,包括訊息中心,外掛管理中心等等的初始化和呼叫

程式碼段4:

入參,都是在CordovaActivity的onCreate中早就初始化好了,這裡只是傳入的,外掛的所有資訊都記錄在
res/xml/config.xml中,這個邏輯比較簡單,就一筆帶過了。

    public void init(CordovaInterface cordova, List<PluginEntry> pluginEntries, CordovaPreferences preferences) {
        if (this.cordova != null) {
            throw new IllegalStateException();
        }
        this.cordova = cordova;
        this.preferences = preferences;//配置中的preference引數
        pluginManager = new PluginManager(this, this.cordova, pluginEntries);//所有的外掛資訊都在這裡管理
        resourceApi = new CordovaResourceApi(engine.getView().getContext(), pluginManager);//可以理解為工具類(資源讀取)
        nativeToJsMessageQueue = new NativeToJsMessageQueue();//之前介紹過的訊息佇列,負責native給js的方法呼叫
        nativeToJsMessageQueue.addBridgeMode(new NativeToJsMessageQueue.NoOpBridgeMode());//封裝成js的方法,
        nativeToJsMessageQueue.addBridgeMode(new NativeToJsMessageQueue.LoadUrlBridgeMode(engine, cordova));

        if (preferences.getBoolean("DisallowOverscroll", false)) {
            engine.getView().setOverScrollMode(View.OVER_SCROLL_NEVER);//滑動是否出現弧形光環
        }
        engine.init(this, cordova, engineClient, resourceApi, pluginManager, nativeToJsMessageQueue);//將所有資訊傳給Engine
        // This isn't enforced by the compiler, so assert here.
        assert engine.getView() instanceof CordovaWebViewEngine.EngineView;

        pluginManager.addService(CoreAndroid.PLUGIN_NAME, "org.apache.cordova.CoreAndroid");//增加一個外掛(這屬於基礎外掛)
        pluginManager.init(); //初始化 程式碼段5

    }

程式碼段5:

    public void init() {
        LOG.d(TAG, "init()");
        isInitialized = true;
        this.onPause(false);//停止
        this.onDestroy();//之前載入的外掛先呼叫onDestroy
        pluginMap.clear();
        this.startupPlugins();//這裡實際上就是將外掛的類物件加入到pluginMap中(LinkedHashMap<String, CordovaPlugin> pluginMap)
    }

這裡在初始化的時候,有兩點需要提一下,外掛分為onLoad外掛和其他外掛,onLoad外掛是啟動時就直接載入的,

其他外掛只有在呼叫的時候,再去初始化後加載。

我們之前的程式碼邏輯呼叫過exec方法,其實就是到這裡的是,再去提取外掛,然後執行固定的程式碼。


到目前位置,應該是所有有疑問的點都已經分析過了,出去cli部分,我們自己構建一套屬於我們自己的架構應該也是沒有問題了

下面就根據我們自己的需求設計我們自己的架構吧。