Cordova Android源碼分析系列二(CordovaWebView相關類分析)

來源:互聯網
上載者:User

標籤:hybrid app   android   cordova   phonegap   

       本篇文章是Cordova Android源碼分析系列文章的第二篇,主要分析CordovaWebView和CordovaWebViewClient類,通過分析代碼可以知道Web網頁載入的過程,錯誤出來,多執行緒等。

CordovaWebView類分析

    CordovaWebView類繼承了Android WebView類,這是一個很自然的實現,共1000多行代碼。包含了PluginManager pluginManager,BroadcastReceiver receiver,CordovaInterface cordova, CordovaWebViewClient viewClient,CordovaChromeClient chromeClient,NativeToJsMessageQueue jsMessageQueue ,ExposedJsApi exposedJsApi,CordovaResourceApi resourceApi等重要的成員變數,與其它核心類關聯起來。

    提供了4個建構函式:CordovaWebView(Context context),CordovaWebView(Context context, AttributeSet attrs, int defStyle, boolean privateBrowsing) ,分別對應Android WebView類的相應建構函式。這些建構函式首先調用WebView的相應建構函式,然後初始化cordova類變數,按情況依次調用自身的setWebChromeClient,initWebViewClient,loadConfiguration,setup方法。

    setWebChromeClient方法設定WebChromeClient,調用了WebView類的setWebChromeClient方法。

    initWebViewClient方法根據Android SDK版本的不同,分別調用setWebViewClient,針對IceCreamSandwich版本,調用setWebViewClient(new IceCreamCordovaWebViewClient(this.cordova, this))。暫時不知道具體的原因。

    /**     * set the WebViewClient, but provide special case handling for IceCreamSandwich.     */    private void initWebViewClient(CordovaInterface cordova) {        if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB ||                android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.JELLY_BEAN_MR1)        {            this.setWebViewClient(new CordovaWebViewClient(this.cordova, this));        }        else        {            this.setWebViewClient(new IceCreamCordovaWebViewClient(this.cordova, this));        }    }


    setup方法的作用是初始化WebView。首先啟用JavaScript,就像我們自己使用WebView時一樣:

  

        WebSettings settings = this.getSettings();        settings.setJavaScriptEnabled(true);        settings.setJavaScriptCanOpenWindowsAutomatically(true);        settings.setLayoutAlgorithm(LayoutAlgorithm.NORMAL);

    

    針對HTC 2.x devices系列裝置設定nav dump(針對ICS禁用,針對Jellybean 4.2降級),具體實現是通過反射拿到setNavDump方法,如果裝置型號中包含HTC並且SDK版本小於11(HONEYCOMB),設定setNavDump(true)。

    設定不儲存網頁表單資料,大家可以放心了!

        //We don‘t save any form data in the application

        settings.setSaveFormData(false);

        settings.setSavePassword(false);

   後面是設定databasePath,是否開啟偵錯模式等,依次調用了setDomStorageEnabled,setGeolocationEnabled,setAppCacheMaxSize,setAppCachePath,setAppCacheEnabled等WebSetting的方法,從名字就可以很容易的理解作用。

   然後註冊了一個receiver,監聽的IntentFilter action是ACTION_CONFIGURATION_CHANGED。

   最後初始化了pluginManager,jsMessageQueue,exposedJsApi,resourceApi成員變數。

   下面我們看下Web頁面載入的流程,先看loadUrl方法,它其實是調用了loadUrlIntoView方法。loadUrlIntoView方法首先會初始化外掛程式管理器pluginManager,然後建立了2個Runnable對象loadError和timeoutCheck,loadError用於通知用戶端viewClient錯誤資訊,timeoutCheck用於檢查頁面逾時,最後在UI線程中調用loadUrlNow(url)。注意timeoutCheck任務是線上程池中啟動並執行。loadUrlNow方法最終調用了WebView的loadUrl(url)方法。

   

        // Load url        this.cordova.getActivity().runOnUiThread(new Runnable() {            public void run() {                cordova.getThreadPool().execute(timeoutCheck);                me.loadUrlNow(url);            }        });


CordovaWebViewClient類分析

    CordovaWebViewClient類繼承了android WebViewClient,實現了CordovaWebView的回掉函數,這些回掉函數在渲染文檔的過程中會被觸發,例如onPageStarted(),shouldOverrideUrlLoading()等方法。

    方法public boolean shouldOverrideUrlLoading(WebView view, String url) 為上層的web應用提供了url載入時處理的機會,js中的exec方法會被攔截,交給handleExecUrl(url)方法處理。如果uri是以tel,sms,geo,market等開頭,這裡會通過Intent啟用相關的App處理。如果是我們自己App或檔案,則會啟動一個新的Activity,包含一個新的CordovaWebView,主要當按返回鍵時,可以返回我們的應用。

    方法public void onPageStarted(WebView view, String url, Bitmap favicon) 通知應用頁面開始載入,如果頁面中包含frameset或iframe,這些嵌入的頁面載入時是不會觸發onPageStarted的。通過this.appView.postMessage方法發送通知給所有外掛程式。

  

@Override    public void onPageStarted(WebView view, String url, Bitmap favicon) {        super.onPageStarted(view, url, favicon);        isCurrentlyLoading = true;        LOG.d(TAG, "onPageStarted(" + url + ")");        // Flush stale messages.        this.appView.jsMessageQueue.reset();        // Broadcast message that page has loaded        this.appView.postMessage("onPageStarted", url);        // Notify all plugins of the navigation, so they can clean up if necessary.        if (this.appView.pluginManager != null) {            this.appView.pluginManager.onReset();        }    }


    方法public void onPageFinished(WebView view, String url) 的實作類別似onPageStarted,需要注意的是頁面載入完成後延時2秒才會停止進度條,目的是防止出現js錯誤或cordova沒有初始化的情況,做法是建立一個線程,sleep 2s,然後在UI線程發送通知spinner stop給所有外掛程式。


 

CordovaResourceApi類分析

Cordova Android使用okhttp架構作為網路訪問基礎架構,okhttp 是一個 Java 的 HTTP+SPDY 用戶端開發包,同時也支援 Android。

CordovaResourceApi封裝了okhttp,主要提供了3個功能:

1.讀寫Url的助手方法

例如處理assets, resources, content providers, files, data URIs, http[s]

可以用來查詢檔案類型和內容長度

2.允許外掛程式重新導向Url

3.通過createHttpConnection()方法暴露Cordova內建的okhttp庫


這個類比較簡單,先是建立了靜態變數OkHttpClient httpClient和jsThread,這樣整個應用只有一個okhttp執行個體,是輕量級實現。

然後建構函式是


public CordovaResourceApi(Context context, PluginManager pluginManager) {

        this.contentResolver = context.getContentResolver();

        this.assetManager = context.getAssets();

        this.pluginManager = pluginManager;

   }

可以看到初始化了contentResolver,assetManager和pluginManager這個類成員變數。

public Uri remapUri(Uri uri) {


        assertNonRelative(uri);

        Uri pluginUri = pluginManager.remapUri(uri);

        return pluginUri != null ? pluginUri : uri;

    }

重新導向Url的方法,url必須是絕對路徑,最終實現在pluginManager.remapUri(uri)

@Override    public void onPageFinished(WebView view, String url) {        super.onPageFinished(view, url);        // Ignore excessive calls.        if (!isCurrentlyLoading) {            return;        }        isCurrentlyLoading = false;        LOG.d(TAG, "onPageFinished(" + url + ")");        /**         * Because of a timing issue we need to clear this history in onPageFinished as well as         * onPageStarted. However we only want to do this if the doClearHistory boolean is set to         * true. You see when you load a url with a # in it which is common in jQuery applications         * onPageStared is not called. Clearing the history at that point would break jQuery apps.         */        if (this.doClearHistory) {            view.clearHistory();            this.doClearHistory = false;        }        // Clear timeout flag        this.appView.loadUrlTimeout++;        // Broadcast message that page has loaded        this.appView.postMessage("onPageFinished", url);        // Make app visible after 2 sec in case there was a JS error and Cordova JS never initialized correctly        if (this.appView.getVisibility() == View.INVISIBLE) {            Thread t = new Thread(new Runnable() {                public void run() {                    try {                        Thread.sleep(2000);                        cordova.getActivity().runOnUiThread(new Runnable() {                            public void run() {                                appView.postMessage("spinner", "stop");                            }                        });                    } catch (InterruptedException e) {                    }                }            });            t.start();        }        // Shutdown if blank loaded        if (url.equals("about:blank")) {            appView.postMessage("exit", null);        }    }



        public File mapUriToFile(Uri uri) 返回url指向的檔案,url可以是file://或content格式,這個方法必須啟動並執行後台線程的斷言,不能運行在UI線程和WebCore線程。


       方法public OpenForReadResult openForRead(Uri uri, boolean skipThreadCheck) throws IOException 用來開啟指定的uri,skipThreadCheck設定是否檢查是否在後台線程運行,返回值OpenForReadResult是個靜態內部類,提供了uri,inputStream,mimeType,內容長度length,AssetFileDescriptor參數,方便我們使用。

      下篇文章分析Cordova外掛程式架構,主要涉及CordovaPlugin和PluginManager類。



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.