H5離線包技術的實際應用-webview秒開

一、背景

在實際業務中,我們app中的webview使用的場景越來越多,加載速度成爲了困擾用戶的一個痛點,尤其是h5由jsp過渡到vue後,頁面加載速度更慢了,經常是經過長時間的loading才能加載出來,雖然這和我們的整體架構有關,首頁有4-7個webview fragment,在進入首頁的時候會同時加載,各個頁面都需要加載大量的圖片以及數個請求。爲此,提高加載速度成爲了優化當中的一個方向。

二、技術探索

在查閱過相關資料後,技術方向大體分爲了兩個,一個是鵝廠的VasSonic通過輔以x5內核對於webview的優化,加上頁面直出,整體加載速度很誇張,在我看來基本逼近了webview的加載極限,但是其難以實現之處在於侵入性很強,需要整體結構向它靠攏,後端、h5、Android三方配合,對於像我們公司以業務爲導向的團隊來說,做起來還比較困難。另一個就是離線包,通常來說,加載一個h5頁面最耗時的部分就在於頁面資源的下載,如html、css、js文件,如果這些文件不需要下載,那麼剩下的時間開銷基本就是頁面解析及渲染。我們Android在和h5溝通過以後,決定採取方案二。

三、技術實現

1.離線包的組成

離線包由h5提供,包裏面的結構基本和線上一致,本身我們的h5網頁就是放在cdn上,這次只不過是拿出來,打成壓縮包,放在Android的apk包裏

2.Android對離線包的解析

首先,離線包的zip包是放在assets文件夾下,在app啓動時,解壓zip包到相應的文件夾目錄下,拿到這個本地路徑

3.對線上地址的替換

webview在加載的時候,會調用loadurl方法,此時傳進去的url還是線上的url,Android要做的最重要的一步就是重寫webviewClient的shouldInterceptRequest方法,在裏面拿到要加載的url,並且進行替換,替換成本地url。同樣的道理,凡事線上資源都可以進行替換,如css、js、圖片資源,還可以通過glide對圖片資源進行緩存。核心代碼如下

    //=============================離線化對webviewclient的改造
    @Nullable
    @Override
    public WebResourceResponse shouldInterceptRequest(WebView view, String urlOrigin) {
        //攔截請求,把本地頁面地址轉換成線上頁面地址
        String url = UrlConfig.replaceUrlHost(urlOrigin);

        String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(url));
        //如果是圖片走緩存
        if (("image/jpeg".equals(mimeType) || "image/png".equals(mimeType)))
            return handleImageRequest(url, mimeType);


        if (UrlConfig.USE_OFFLINE && !url.contains("http")) {
            //構建WebResourceResponse,走重寫後的方法。super會直接load傳進來的urlOrigin
            try {
                URL localUri = new URL(url);
                InputStream is = localUri.openConnection().getInputStream();
                return new WebResourceResponse(
                        MimeTypeMap.getSingleton().getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(url))
                        , "UTF-8", is);

            } catch (IOException e) {
                //如果文件找不到,攔截方法會失效,還是走之前的url
                if (e.getMessage().contains(".js")) {
                    //當前線程-Chrome_FileThread
                    webview.getHandler().post(new Runnable() {
                        @Override
                        public void run() {
                            onError.onErrorReceived();//處理白屏的情況,缺少js文件會走onError
                            C.OFFLINE_LOADFAIL = true;
                        }
                    });
                }

                e.printStackTrace();
            }
        }
        return super.shouldInterceptRequest(view, url);
    }

註釋1:UrlConfig.replaceUrlHost方法裏面是具體替換過程。舉個例子:線上地址肯定是 ww.baidu.com/index.html這種,本地地址就是file:///storage/0/emulate/baidu/index.html,把index.html之前做字符串替換就可以。

四、最終效果

經過測試同學的性能測試,頁面首次加載提升率平均50%,二次加載平均提升35%;由於網絡請求也是Android代替h5請求,所以request請求提升超過80%,這些數據是正常網絡狀態下,而在弱網狀態下更是有超過300%的提升

================================================================================================

如有問題,可加1510312433交流

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章