Android WebView 優(yōu)化匯總

目錄

  • 引言:Html加載流程
  • 加載流程各節(jié)點(diǎn)耗時(shí)分析優(yōu)化
  • 加載流程結(jié)構(gòu)優(yōu)化
  • 客戶端優(yōu)化

Html加載流程

  1. 創(chuàng)建并初始化WebView
  2. 下載網(wǎng)頁所需資源文件
  3. 渲染展示網(wǎng)頁
HTML加載流程.png

加載流程各節(jié)點(diǎn)耗時(shí)分析優(yōu)化

  • WebView創(chuàng)建初始化
    首次初始化WebView會(huì)比第二次初始化慢很多臊诊。初始化后另锋,即使WebView已釋放,但一些多WebView共用的全局服務(wù)/資源對想仍未釋放摘能,而第二次初始化不需要生成腔彰,因此初始化變快诵盼。

    1. 提前初始化, 提前預(yù)備全局WebView畅卓,Application中初始化WebView備用
    
     @Override
     public void onCreate() {
          // Application中提前初始化WebView
          WebView mWebView = new WebView(new MutableContextWrapper(this))
     }
    

    注:該方式會(huì)增加冷啟動(dòng)時(shí)間

    2. WebView復(fù)用绊袋,維護(hù)WebView pool,避免每次打開網(wǎng)頁創(chuàng)建WebView璃岳。
    

    例如:VasSonic方案

  • DNS解析耗時(shí)
    html網(wǎng)頁文件獲取過程中年缎,首先需要將url鏈接解析成ip地址,根據(jù)ip地址獲取到對應(yīng)html文件铃慷。

    1. DNS會(huì)在系統(tǒng)級別進(jìn)行緩存单芜,對于WebView的地址,如果使用的域名與原生api的相同犁柜,則可直接使用緩存洲鸠,避免DNS解析耗時(shí)。
    
  • 資源文件下載耗時(shí)
    弱網(wǎng)情況下馋缅,下載網(wǎng)頁資源耗時(shí)扒腕,導(dǎo)致白屏?xí)r間過長。

    1. 網(wǎng)頁資源壓縮萤悴,并CDN加速處理瘾腰,縮短請求耗時(shí)。 
    2. 服務(wù)端下發(fā)填充好首屏數(shù)據(jù)的網(wǎng)頁稚疹,作為網(wǎng)頁首屏展示居灯,減少網(wǎng)頁上數(shù)據(jù)請求時(shí)間。
    3. App閑置狀態(tài)時(shí)内狗,下載離線包到本地怪嫌,加載時(shí)優(yōu)先加載離線包數(shù)據(jù)。后續(xù)更新接收下發(fā)的差異包柳沙,與當(dāng)前離線包合并成完整包岩灭。
    
  • HTML解析耗時(shí)
    解析html文件,構(gòu)建DOM樹赂鲤,耗時(shí)取決于html節(jié)點(diǎn)嵌套復(fù)雜程度噪径,與硬件解析能力強(qiáng)弱柱恤。

  • css文件加載解析、js加載
    一般來說Html在開始接收到數(shù)據(jù)返回?cái)?shù)據(jù)時(shí)就開始解析并構(gòu)建DOM樹找爱,如果沒有JS阻塞的話一般會(huì)相繼完成梗顺,通常情況下,下面代碼的link部分和script部分如果單獨(dú)出現(xiàn)车摄,都不會(huì)阻塞頁面的解析寺谤,但,當(dāng)兩部分同時(shí)出現(xiàn)時(shí)吮播,css加載會(huì)阻塞下面的內(nèi)聯(lián)JS的執(zhí)行变屁,從而阻塞阻塞Html文件的解析。

    1. 為防止JS阻塞Html的解析意狠,Web端需延遲JS解析粟关。
    
  • 繪制渲染
    布局繪制是一個(gè)遞歸過程,從呈現(xiàn)根節(jié)點(diǎn)開始环戈,遞歸遍歷子節(jié)點(diǎn)闷板,計(jì)算幾何集合信息。因此谷市,html標(biāo)簽越復(fù)雜蛔垢、嵌套越深击孩,則布局耗時(shí)越久迫悠。

    1. 優(yōu)化網(wǎng)頁布局,減少布局層次巩梢。
    

加載流程結(jié)構(gòu)優(yōu)化

  • 流程優(yōu)化
    默認(rèn)狀態(tài)下创泄,WebView初始化與資源文件下載為線性同步執(zhí)行,此時(shí)WebView初始化時(shí)括蝠,網(wǎng)絡(luò)為空閑狀態(tài)鞠抑,并行處理WebView初始化與資源文件下載可縮短網(wǎng)頁顯示的總耗時(shí)。

    第一階段為:創(chuàng)建初始化WebView(Launch WebView)
    第二階段為:請求網(wǎng)頁資源(Native(Sonic) Request)

串行模式.png

并行模式.png

但忌警,由于WebView初始化與請求網(wǎng)頁資源操作結(jié)束時(shí)間先后無可得知搁拙。

方案:流式攔截,加入中間層來橋接內(nèi)核和數(shù)據(jù)

  1. 啟動(dòng)子線程請求頁面主資源法绵,子線程中不斷將網(wǎng)絡(luò)數(shù)據(jù)讀取到內(nèi)存中箕速。
  2. WebView初始化完成的時(shí)候,提供中間層BridgeStream來連接WebView和數(shù)據(jù)流朋譬;
  3. WebView讀取數(shù)據(jù)時(shí)盐茎,中間層BridgeStream先把內(nèi)存的數(shù)據(jù)讀取返回后,再繼續(xù)讀取網(wǎng)絡(luò)的數(shù)據(jù)徙赢。
中間件.png

通過橋接流的方式字柠,整個(gè)內(nèi)核無需等待探越,邊加載邊解析

客戶端優(yōu)化

  • 合理使用WebView提供的幾種緩存方式
    1. 瀏覽器緩存。內(nèi)置自動(dòng)實(shí)現(xiàn)
    2. Application Cache 緩存

    webSettings.setAppCacheEnabled(true)
    webSettings.setAppCacheMaxSize(yourCacheSize)
    webSettings.setAppCachePath(yourCacheDirPath)

    1. DOM Storage 緩存

    setDomStorageEnabled(true)

    1. Web SQL Database 緩存

    webSettings.setDatabaseEnabled(true)
    webSettings.setDatabasePath(yourCacheDirPath)

    1. Indexed Database 緩存窑业。Android 4.4以上支持

    webSettings.setJavaScriptEnabled(true)

如何緩存html钦幔、js、css常柄、圖片等文件节槐,通過緩存機(jī)制,對于應(yīng)用提高資源文件的加載速度拐纱、流量優(yōu)化有很大意義铜异。而具體該針對哪種資源使用哪個(gè)緩存字段,以及緩存時(shí)長設(shè)置就比較重要秸架。若時(shí)長設(shè)置的太短揍庄,則緩存效果受影響,若時(shí)長設(shè)置過長东抹,則不能及時(shí)獲取服務(wù)器最新數(shù)據(jù)蚂子。

  • html、js缭黔、css資源
    考慮到這些文件會(huì)隨著業(yè)務(wù)需求經(jīng)常變化食茎。為此,這些文件可以使用Last-Modified(Etag)來控制緩存

  • 圖片馏谨、音視頻資源
    圖片也可以通過Last-Modified(Etag)來控制緩存别渔。但這樣每次都需向服務(wù)器發(fā)起查詢請求,考慮到圖片文件長時(shí)間變動(dòng)不大惧互,推薦使用Cache-Control設(shè)置一個(gè)較長的時(shí)間來緩存哎媚。

  • 除此之外,也可以使用Application Cache機(jī)制喊儡,由前端控制緩存文件拨与,客戶端設(shè)置緩存路徑和大小。

由于艾猜,WebView各緩存機(jī)制的緩存大小有限买喧,時(shí)常導(dǎo)致最開始的緩存被清理;瀏覽器緩存Last-ModiedETag控制不完全匆赃,依然無法很好的避免過渡請求網(wǎng)頁資源淤毛,因此,需要一套可控的緩存策略炸庞,來突破緩存容量過小和圖片緩存策略統(tǒng)一的問題钱床。

  • 資源本地化
    網(wǎng)頁加載到顯示,需要下載大量文件埠居,其中不乏有些體積大并且基本固定不動(dòng)的資源查牌,此時(shí)事期,可把這些資源預(yù)置在項(xiàng)目中,加載時(shí)從本地加載纸颜,方案與離線包方案類似兽泣。

    資源本地化.png

    大致操作如下:
    1. 方式一、JS方法注入
   // 1. 固定資源放到項(xiàng)目文件夾胁孙,如/Assets文件夾中 
   // 2. 注入JS方法
   webView.addJavascriptInterface(new JsInterface(), "JsInterface")
   private class JsInterface {
      @JavascriptInterface
      public String getLocalSrc(String src) {
           return "file://storage/emulated/0/app/file/a.jpeg"
      }
   }
   // 3. 頁面加載完成時(shí)唠倦,修改圖片標(biāo)簽
   private class MyWebViewClient extends WebViewClient {

    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        String js = "javascript:(function() {
             var objs = document.getElementsByTagName('img');
             for (var i = 0; i < objs.length; i++)  {
                  var imgUrl = objs[i].getAttribute('src'); 
                  var localUrl = window.local_obj.getLocalSrc(imgUrl); 
                  if (localUrl) { 
                      objs[i].setAttribute('src', localUrl);
                  }
             }
        })()"

        view.loadUrl(js);
    }
}
  1. 方式二、請求攔截
  webView.setWebViewClient(new WebViewClient() {
      // 為方便涮较,此處進(jìn)寫Api 21以下方法稠鼻,Api21 以上雷同
      @Override
      public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
           // 1. 判斷攔截資源的條件
           if (url.contains("logo.gif")) {
                // 假設(shè)網(wǎng)頁圖片資源為:http://abc.com/image/logo.gif
                // 圖片資源文件名為:logo.gif

                // 2. 創(chuàng)建輸入流
                InputStream is = null

                try {
                    // 3. 獲得需要替換的資源(存放在assets文件夾中)
                    is = getApplicationContext().getAssets().open("image/abc.png") 
                } catch (IOException e) {
                    e.printStackTrace()
                }

                // 4. 替換資源
                WebResourceResponse reponse = new WebResourceResponse("image/png", "utf-8", is)
                return response
           }
           return super.shouldInterceptRequest(view, url)
      }
  })

此外,客戶端需要預(yù)置資源狂票,并維護(hù)網(wǎng)絡(luò)圖片url和本地圖片自檢的關(guān)聯(lián)候齿,根據(jù)一定策略保證本地預(yù)置資源為最新資源。若預(yù)置資源不限于圖片資源闺属,由于html慌盯、js、css等資源容易發(fā)生變化掂器,因此還需實(shí)現(xiàn)一套機(jī)制實(shí)現(xiàn)本地資源和服務(wù)端數(shù)據(jù)及時(shí)的更新亚皂。即服務(wù)端需要支持版本控制和資源增量下發(fā)等功能。

總結(jié)

結(jié)合手Q国瓮、網(wǎng)易嚴(yán)選灭必、美團(tuán)等其他方面優(yōu)化方案,大致如下:
  • WebView在Application中提前初始化
  • 實(shí)現(xiàn)WebView復(fù)用
  • 另開WebView進(jìn)程
  • DNS解析優(yōu)化(接口與網(wǎng)頁主域名一致)
  • 線上資源壓縮巍膘、CDN加速
  • 靜態(tài)直出厂财,直接下發(fā)首屏html
  • 離線預(yù)推,下發(fā)離線包峡懈,并增量更新
  • WebView創(chuàng)建與網(wǎng)絡(luò)請求并行
  • 網(wǎng)頁按節(jié)點(diǎn)局部刷新
  • 自定義實(shí)現(xiàn)圖片資源緩存
  • 重新定義圖片加載格式,shareP
  • 本地資源攔截替換
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末与斤,一起剝皮案震驚了整個(gè)濱河市肪康,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌撩穿,老刑警劉巖磷支,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異食寡,居然都是意外死亡雾狈,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門抵皱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來善榛,“玉大人辩蛋,你說我怎么就攤上這事∫婆瑁” “怎么了悼院?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長咒循。 經(jīng)常有香客問我据途,道長,這世上最難降的妖魔是什么叙甸? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任颖医,我火速辦了婚禮,結(jié)果婚禮上裆蒸,老公的妹妹穿的比我還像新娘便脊。我一直安慰自己,他們只是感情好光戈,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布哪痰。 她就那樣靜靜地躺著,像睡著了一般久妆。 火紅的嫁衣襯著肌膚如雪晌杰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天筷弦,我揣著相機(jī)與錄音肋演,去河邊找鬼。 笑死烂琴,一個(gè)胖子當(dāng)著我的面吹牛爹殊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播奸绷,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼梗夸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了号醉?” 一聲冷哼從身側(cè)響起反症,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎畔派,沒想到半個(gè)月后铅碍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡线椰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年胞谈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡烦绳,死狀恐怖卿捎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情爵嗅,我是刑警寧澤娇澎,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站睹晒,受9級特大地震影響趟庄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜伪很,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一戚啥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锉试,春花似錦猫十、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至应又,卻和暖如春宙项,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背株扛。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工尤筐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人洞就。 一個(gè)月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓盆繁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親旬蟋。 傳聞我的和親對象是個(gè)殘疾皇子油昂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

推薦閱讀更多精彩內(nèi)容