WebView庫(kù)功能完善

目錄介紹

  • 01.loadUrl到底做了什么
  • 02.觸發(fā)加載網(wǎng)頁(yè)的行為
  • 03.webView重定向怎么辦
  • 04.js交互的一點(diǎn)知識(shí)分享
  • 05.攔截緩存如何優(yōu)雅處理
  • 06.關(guān)于一些問題和優(yōu)化
  • 07.關(guān)于一點(diǎn)面向?qū)ο笏枷?/li>
  • 08.關(guān)于后期需要研究目標(biāo)

01.loadUrl到底做了什么

  • WebView.loadUrl(url)加載網(wǎng)頁(yè)做了什么尚氛?
    • 加載網(wǎng)頁(yè)是一個(gè)復(fù)雜的過程队萤,在這個(gè)過程中,我們可能需要執(zhí)行一些操作嘉涌,包括:
    • 加載網(wǎng)頁(yè)前砰逻,重置WebView狀態(tài)以及與業(yè)務(wù)綁定的變量狀態(tài)韭邓。WebView狀態(tài)包括重定向狀態(tài)(mTouchByUser)橱健、前端控制的回退棧(mBackStep)等斯撮,業(yè)務(wù)狀態(tài)包括進(jìn)度條批幌、當(dāng)前頁(yè)的分享內(nèi)容础锐、分享按鈕的顯示隱藏等。
    • 加載網(wǎng)頁(yè)前荧缘,根據(jù)不同的域拼接本地客戶端的參數(shù)皆警,包括基本的機(jī)型信息、版本信息截粗、登錄信息以及埋點(diǎn)使用的Refer信息等信姓,有時(shí)候涉及交易、財(cái)產(chǎn)等還需要做額外的配置绸罗。
    • 開始執(zhí)行頁(yè)面加載操作時(shí)意推,會(huì)回調(diào)WebViewClient.onPageStarted(webView,url,favicon)。在此方法中珊蟀,可以重置重定向保護(hù)的變量(mRedirectProtected)菊值,當(dāng)然也可以在頁(yè)面加載前重置,由于歷史遺留代碼問題育灸,此處尚未省去優(yōu)化腻窒。
  • 加載頁(yè)面的過程中回調(diào)哪些方法?
    • WebChromeClient.onReceivedTitle(webview, title)磅崭,用來設(shè)置標(biāo)題儿子。需要注意的是,在部分Android系統(tǒng)版本中可能會(huì)回調(diào)多次這個(gè)方法砸喻,而且有時(shí)候回調(diào)的title是一個(gè)url柔逼,客戶端可以針對(duì)這種情況進(jìn)行特殊處理,避免在標(biāo)題欄顯示不必要的鏈接恩够。
    • WebChromeClient.onProgressChanged(webview, progress)卒落,根據(jù)這個(gè)回調(diào)羡铲,可以控制進(jìn)度條的進(jìn)度(包括顯示與隱藏)蜂桶。一般情況下,想要達(dá)到100%的進(jìn)度需要的時(shí)間較長(zhǎng)(特別是首次加載)也切,用戶長(zhǎng)時(shí)間等待進(jìn)度條不消失必定會(huì)感到焦慮扑媚,影響體驗(yàn)腰湾。其實(shí)當(dāng)progress達(dá)到80的時(shí)候,加載出來的頁(yè)面已經(jīng)基本可用了疆股。事實(shí)上费坊,國(guó)內(nèi)廠商大部分都會(huì)提前隱藏進(jìn)度條,讓用戶以為網(wǎng)頁(yè)加載很快旬痹。
    • WebViewClient.shouldInterceptRequest(webview, request)附井,無論是普通的頁(yè)面請(qǐng)求(使用GET/POST),還是頁(yè)面中的異步請(qǐng)求两残,或者頁(yè)面中的資源請(qǐng)求永毅,都會(huì)回調(diào)這個(gè)方法,給開發(fā)一次攔截請(qǐng)求的機(jī)會(huì)人弓。在這個(gè)方法中沼死,我們可以進(jìn)行靜態(tài)資源的攔截并使用緩存數(shù)據(jù)代替,也可以攔截頁(yè)面崔赌,使用自己的網(wǎng)絡(luò)框架來請(qǐng)求數(shù)據(jù)意蛀。包括后面介紹的WebView免流方案,也和此方法有關(guān)健芭。
    • WebViewClient.shouldOverrideUrlLoading(webview, request)县钥,如果遇到了重定向,或者點(diǎn)擊了頁(yè)面中的a標(biāo)簽實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)吟榴,那么會(huì)回調(diào)這個(gè)方法魁蒜。可以說這個(gè)是WebView里面最重要的回調(diào)之一吩翻,后面WebView與Native頁(yè)面交互一節(jié)將會(huì)詳細(xì)介紹這個(gè)方法兜看。
    • WebViewClient.onReceivedError(webview,handler,error),加載頁(yè)面的過程中發(fā)生了錯(cuò)誤狭瞎,會(huì)回調(diào)這個(gè)方法细移。主要是http錯(cuò)誤以及ssl錯(cuò)誤。在這兩個(gè)回調(diào)中熊锭,我們可以進(jìn)行異常上報(bào)弧轧,監(jiān)控異常頁(yè)面、過期頁(yè)面碗殷,及時(shí)反饋給運(yùn)營(yíng)或前端修改精绎。在處理ssl錯(cuò)誤時(shí),遇到不信任的證書可以進(jìn)行特殊處理锌妻,例如對(duì)域名進(jìn)行判斷代乃,針對(duì)自己公司的域名“放行”,防止進(jìn)入丑陋的錯(cuò)誤證書頁(yè)面。也可以與Chrome一樣搁吓,彈出ssl證書疑問彈窗原茅,給用戶選擇的余地。
  • 加載頁(yè)面結(jié)束回調(diào)哪些方法
    • 會(huì)回調(diào)WebViewClient.onPageFinished(webview,url)堕仔。
    • 這時(shí)候可以根據(jù)回退棧的情況判斷是否顯示關(guān)閉WebView按鈕擂橘。通過mActivityWeb.canGoBackOrForward(-1)判斷是否可以回退。

02.觸發(fā)加載網(wǎng)頁(yè)的行為

  • 觸發(fā)加載網(wǎng)頁(yè)的行為主要有兩種方式:
    • (A)點(diǎn)擊頁(yè)面摩骨,觸發(fā)<link>標(biāo)簽通贞。
    • (B)調(diào)用WebView的loadUrl()方法
    • 這兩種方法都會(huì)發(fā)出一條地址,區(qū)別就在于這條地址是目的地址還是重定向地址恼五。以訪問http://www.baidu.com百度的頁(yè)面來測(cè)試一下方法的執(zhí)行順序滑频。
  • 觸發(fā)加載網(wǎng)頁(yè)流程分析
    • 在代碼中通過loadUrl加載百度的首頁(yè),此時(shí)的行為屬于(B)方式唤冈。
      • 可以發(fā)現(xiàn)大概的執(zhí)行順序是:onPageStarted ——> shouldOverrideUrlLoading ——> onPageFinished
      • 那么為什么會(huì)執(zhí)行多次呢峡迷,思考一下?具體可以看一下7.2得出的結(jié)論分析你虹。
      X5LogUtils: -------onPageStarted-------http://www.baidu.com/
      X5LogUtils: -------shouldOverrideUrlLoading-------https://m.baidu.com/?from=844b&vit=fps
      X5LogUtils: -------onPageFinished-------http://www.baidu.com/
      X5LogUtils: -------onPageStarted-------https://m.baidu.com/?from=844b&vit=fps
      X5LogUtils: -------onReceivedTitle-------百度一下
      X5LogUtils: -------shouldOverrideUrlLoading-------http://m.baidu.com/?cip=117.101.19.67&baiduid=C6FCEED198C994E0D653C094F2708C32&from=844b&vit=fps?from=844b&vit=fps&index=&ssid=0&bd_page_type=1&logid=12175252243175665635&pu=sz%401321_480&t_noscript=jump
      X5LogUtils: -------onPageFinished-------https://m.baidu.com/?from=844b&vit=fps
      X5LogUtils: -------shouldOverrideUrlLoading-------https://m.baidu.com/?cip=117.101.19.67&baiduid=C6FCEED198C994E0D653C094F2708C32&from=844b&vit=fps?from=844b&vit=fps&index=&ssid=0&bd_page_type=1&logid=12175252243175665635&pu=sz%401321_480&t_noscript=jump
      X5LogUtils: -------onPageStarted-------http://m.baidu.com/?cip=117.101.19.67&baiduid=C6FCEED198C994E0D653C094F2708C32&from=844b&vit=fps?from=844b&vit=fps&index=&ssid=0&bd_page_type=1&logid=12175252243175665635&pu=sz%401321_480&t_noscript=jump
      X5LogUtils: -------onPageFinished-------http://m.baidu.com/?cip=117.101.19.67&baiduid=C6FCEED198C994E0D653C094F2708C32&from=844b&vit=fps?from=844b&vit=fps&index=&ssid=0&bd_page_type=1&logid=12175252243175665635&pu=sz%401321_480&t_noscript=jump
      X5LogUtils: -------onPageStarted-------https://m.baidu.com/?cip=117.101.19.67&baiduid=C6FCEED198C994E0D653C094F2708C32&from=844b&vit=fps?from=844b&vit=fps&index=&ssid=0&bd_page_type=1&logid=12175252243175665635&pu=sz%401321_480&t_noscript=jump
      X5LogUtils: -------onReceivedTitle-------百度一下,你就知道
      X5LogUtils: -------onPageFinished-------https://m.baidu.com/?cip=117.101.19.67&baiduid=C6FCEED198C994E0D653C094F2708C32&from=844b&vit=fps?from=844b&vit=fps&index=&ssid=0&bd_page_type=1&logid=12175252243175665635&pu=sz%401321_480&t_noscript=jump
      
    • 在首頁(yè)绘搞,點(diǎn)擊一下“hao123”,跳轉(zhuǎn)到www.hao123.com的主頁(yè)上來,此時(shí)的行為屬于(A)方式傅物。
      • 可以發(fā)現(xiàn)大概的執(zhí)行順序是:shouldOverrideUrlLoading ——> onPageStarted ——> onPageFinished
      X5LogUtils: -------shouldOverrideUrlLoading-------http://m.hao123.com/?ssid=0&from=844b&bd_page_type=1&uid=0&pu=sz%401321_1002%2Cta%40utouch_2_9.0_2_6.2&idx=30000&itj=39
      X5LogUtils: -------onPageStarted-------http://m.hao123.com/?ssid=0&from=844b&bd_page_type=1&uid=0&pu=sz%401321_1002%2Cta%40utouch_2_9.0_2_6.2&idx=30000&itj=39
      X5LogUtils: -------onReceivedTitle-------hao123導(dǎo)航-上網(wǎng)從這里開始
      X5LogUtils: -------onPageFinished-------http://m.hao123.com/?ssid=0&from=844b&bd_page_type=1&uid=0&pu=sz%401321_1002%2Cta%40utouch_2_9.0_2_6.2&idx=30000&itj=39
      
    • 然后在hao123頁(yè)面夯辖,點(diǎn)擊優(yōu)酷網(wǎng)進(jìn)行跳轉(zhuǎn),此時(shí)的行為屬于(A)方式董饰。
      X5LogUtils: -------shouldOverrideUrlLoading-------http://m.hao123.com/j.php?z=2&page=index_cxv3&pos=cydhwt_n2&category=ty&title=%E4%BC%98%E9%85%B7%E7%BD%91&qt=tz&url=http%3A%2F%2Fwww.youku.com%2F&key=58193753e7a868d9a013056c6c4cd77b
      X5LogUtils: -------onPageStarted-------http://m.hao123.com/j.php?z=2&page=index_cxv3&pos=cydhwt_n2&category=ty&title=%E4%BC%98%E9%85%B7%E7%BD%91&qt=tz&url=http%3A%2F%2Fwww.youku.com%2F&key=58193753e7a868d9a013056c6c4cd77b
      X5LogUtils: -------shouldOverrideUrlLoading-------http://www.youku.com/
      X5LogUtils: -------onPageFinished-------http://m.hao123.com/j.php?z=2&page=index_cxv3&pos=cydhwt_n2&category=ty&title=%E4%BC%98%E9%85%B7%E7%BD%91&qt=tz&url=http%3A%2F%2Fwww.youku.com%2F&key=58193753e7a868d9a013056c6c4cd77b
      X5LogUtils: -------onPageStarted-------http://www.youku.com/
      X5LogUtils: -------shouldOverrideUrlLoading-------https://www.youku.com/
      X5LogUtils: -------onPageFinished-------http://www.youku.com/
      X5LogUtils: -------onPageStarted-------https://www.youku.com/
      X5LogUtils: -------onReceivedTitle-------優(yōu)酷視頻-首頁(yè)
      X5LogUtils: -------onPageFinished-------https://www.youku.com/
      
    • 然后從優(yōu)酷頁(yè)面回退到hao123頁(yè)面蒿褂,看看又回執(zhí)行哪些方法。
      X5LogUtils: -------onPageStarted-------http://m.hao123.com/?ssid=0&from=844b&bd_page_type=1&uid=0&pu=sz%401321_1002%2Cta%40utouch_2_9.0_2_6.2&idx=30000&itj=39
      X5LogUtils: -------onReceivedTitle-------hao123導(dǎo)航-上網(wǎng)從這里開始
      X5LogUtils: -------onReceivedTitle-------hao123導(dǎo)航-上網(wǎng)從這里開始
      X5LogUtils: -------onPageFinished-------http://m.hao123.com/?ssid=0&from=844b&bd_page_type=1&uid=0&pu=sz%401321_1002%2Cta%40utouch_2_9.0_2_6.2&idx=30000&itj=39
      
    • 然后從hao123頁(yè)面回退到百度首頁(yè)卒暂,看看又回執(zhí)行哪些方法啄栓。
      X5LogUtils: -------onPageStarted-------https://m.baidu.com/?cip=117.101.19.67&baiduid=C6FCEED198C994E0D653C094F2708C32&from=844b&vit=fps?from=844b&vit=fps&index=&ssid=0&bd_page_type=1&logid=12175252243175665635&pu=sz%401321_480&t_noscript=jump
      X5LogUtils: -------onReceivedTitle-------百度一下,你就知道
      X5LogUtils: -------onReceivedTitle-------百度一下,你就知道
      X5LogUtils: -------onPageFinished-------https://m.baidu.com/?cip=117.101.19.67&baiduid=C6FCEED198C994E0D653C094F2708C32&from=844b&vit=fps?from=844b&vit=fps&index=&ssid=0&bd_page_type=1&logid=12175252243175665635&pu=sz%401321_480&t_noscript=jump
      
  • 得出結(jié)論分析說明
    • 在(A)行為方式下(用戶點(diǎn)擊鏈接的回調(diào)):
      • 1.如果是目的地址,那么方法的執(zhí)行順序是:
        • shouldOverrideUrlLoading() -> onPageStarted()-> onPageFinished()
        • shouldOverrideUrlLoading()由于它要提供給APP選擇加載網(wǎng)頁(yè)環(huán)境的機(jī)會(huì)也祠,所以只要是網(wǎng)頁(yè)上地址請(qǐng)求昙楚,都會(huì)獲取到。
      • 2.如果是重定向地址诈嘿,在跳轉(zhuǎn)到目的地址之前會(huì)進(jìn)行不斷的地址定位堪旧,每一次地址定位都會(huì)由以下執(zhí)行順序體現(xiàn)出來:
        • onPageStarted()->shouldOverrideUrlLoading()->onPageFinished()
        • 暫且設(shè)定這種執(zhí)行順序叫:fixed position
        • 那么一個(gè)正常的重定向地址,方法的執(zhí)行順序就是:
        • shouldOverrideUrlLoading() -> fixed position -> … -> fixed position -> onPageStarted() -> onPageFinished()
        • 舉個(gè)例子:有重定向(A->B->C)奖亚,那么
        shouldOverrideUrlLoading(A) -> onPageStarted(A) ->
        onPageStarted(B) -> shouldOverrideUrlLoading(B) ->
        onPageStarted(C) -> shouldOverrideUrlLoading(C) -> onPageFinished(C)
        
    • 在(B)行為下:
      • 1.如果是目的地址淳梦,那么方法的執(zhí)行順序是:
        • onPageStarted()-> onPageFinished()
        • loadUrl()加載地址時(shí),一般不會(huì)觸發(fā)shouldOverrideUrlLoading()昔字,一旦觸發(fā)了爆袍,就說明這是一個(gè)重定向地址。
      • 2.如果是重定向地址,方法的執(zhí)行順序就是:
        • fixed position -> … -> fixed position -> onPageStarted() -> onPageFinished()

03.webView重定向怎么辦

  • webView出現(xiàn)302/303重定向
    • 302重定向又稱之為302代表暫時(shí)性轉(zhuǎn)移螃宙,比如你跳轉(zhuǎn)A頁(yè)面,但由于網(wǎng)頁(yè)添加了約束條件所坯,可能讓你跳轉(zhuǎn)到B頁(yè)面谆扎,甚至多次重定向。
  • 導(dǎo)致的問題
    • 1.A-->B-->C芹助,比如你跳轉(zhuǎn)A頁(yè)面堂湖,最終重定向到C頁(yè)面。這個(gè)時(shí)候調(diào)用goBack方法状土,返回到B鏈接无蜂,但是B鏈接又會(huì)跳轉(zhuǎn)到C鏈接,從而導(dǎo)致沒法返回到A鏈接界面
    • 2.會(huì)多次執(zhí)行onPageStarted和onPageFinished蒙谓,如果你這里有加載進(jìn)度條或者loading斥季,那么會(huì)導(dǎo)致進(jìn)度條或者loading執(zhí)行多次
  • 常見的解決方案
  • 如何判斷重定向
    • 通過getHitTestResult()返回值置侍,如果返回null映之,或者UNKNOWN_TYPE,則表示為重定向。具體看:18.如何用代碼判斷是否重定向
    • 在加載一個(gè)頁(yè)面開始的時(shí)候會(huì)回調(diào)onPageStarted方法,在該頁(yè)面加載完成之后會(huì)回調(diào)onPageFinished方法哨坪。而如果該鏈接發(fā)生了重定向帜乞,回調(diào)shouldOverrideUrlLoading會(huì)在回調(diào)onPageFinished之前。
  • 終極解決方案如下
    • 需要準(zhǔn)備的條件
      • 創(chuàng)建一個(gè)棧卿叽,主要是用來存取和移除url的操作。這個(gè)url包括所有的請(qǐng)求鏈接
      • 定義一個(gè)變量,用于判斷頁(yè)面是否處于正在加載中峡钓。
      • 定義一個(gè)變量,用于記錄重定向前的鏈接url
      • 定一個(gè)重定向時(shí)間間隔若河,主要為了避免刷新造成循環(huán)重定向
    • 具體怎么操作呢
      • 在執(zhí)行onPageStarted時(shí)能岩,先移除棧中上一個(gè)url,然后將url加載到棧中萧福。
      • 當(dāng)出現(xiàn)錯(cuò)誤重定向的時(shí)候拉鹃,如果和上一次重定向的時(shí)間間隔大于3秒,則reload頁(yè)面。
      • 在回退操作的時(shí)候膏燕,判斷如果可以回退钥屈,則從棧中獲取最后停留的url,然后loadUrl坝辫。即可解決回退問題篷就。
    • 具體方法思路

04.js交互的一點(diǎn)知識(shí)分享

  • js交互介紹
    • Java調(diào)用js方法有兩種:
      • WebView.loadUrl("javascript:" + javascript);
      • WebView.evaluateJavascript(javascript, callbacck);
    • js調(diào)用Java的方法有三種,分別是:
      • JavascriptInterface
      • WebViewClient.shouldOverrideUrlLoading()
      • WebChromeClient.onJsPrompt()
  • js調(diào)用java方法比較和區(qū)別分析
    • 1.通過 addJavascriptInterface 方法進(jìn)行添加對(duì)象映射近忙。js最終通過對(duì)象調(diào)用原生方法
    • 2.shouldOverrideUrlLoading攔截操作竭业,獲取scheme匹配,與網(wǎng)頁(yè)約定好一個(gè)協(xié)議及舍,如果匹配未辆,執(zhí)行相應(yīng)操作
    • 3.利用WebChromeClient回調(diào)接口onJsPrompt攔截操作。
      • onJsAlert 是不能返回值的锯玛,而 onJsConfirm 只能夠返回確定或者取消兩個(gè)值咐柜,只有 onJsPrompt 方法是可以返回字符串類型的值,操作最全面方便攘残。
    • 詳細(xì)分析可以看:03.Js調(diào)用Android
  • js調(diào)用java原生方法可能存在的問題炕桨?
    • 提出問題
      • 1.原生方法是否可以執(zhí)行耗時(shí)操作,如果有會(huì)阻塞通信嗎肯腕?4.4.8 prompt的一個(gè)坑導(dǎo)致js掛掉
      • 2.多線程中調(diào)用多個(gè)原生方法献宫,如何保證原生方法每一個(gè)都會(huì)被執(zhí)行到?
      • 3.js會(huì)阻塞等待當(dāng)前原生函數(shù)(耗時(shí)操作的那個(gè))執(zhí)行完畢再往下走实撒,所以js調(diào)用java方法里面最好也不要做耗時(shí)操作
    • 解決方案
      • 1.在js調(diào)用?window.alert?姊途,?window.confirm?,?window.prompt?時(shí)知态,?會(huì)調(diào)用WebChromeClient?對(duì)應(yīng)方法捷兰,可以此為入口,作為消息傳遞通道负敏,考慮到開發(fā)習(xí)慣贡茅,一般不會(huì)選擇alert跟confirm,?通常會(huì)選prompt作為入口其做,在App中就是onJsPrompt作為jsbridge的調(diào)用入口顶考。由于onJsPrompt是在UI線程執(zhí)行,所以盡量不要做耗時(shí)操作妖泄,可以借助Handler靈活處理驹沿。
      • 2.利用Handler封裝一下,讓每個(gè)任務(wù)自己處理蹈胡,耗時(shí)的話就開線程自己處理渊季。具體可以看:WvWebView
  • java調(diào)用js的時(shí)機(jī)
    • onPageFinished()或者onPageStarted()方法中注入js代碼嗎朋蔫?
      • js交互,大部分都會(huì)認(rèn)為js在WebViewClient.onPageFinished()方法中注入最合適却汉,此時(shí)dom樹已經(jīng)構(gòu)建完成驯妄,頁(yè)面已經(jīng)完全展現(xiàn)出來。但如果做過頁(yè)面加載速度的測(cè)試合砂,會(huì)發(fā)現(xiàn)WebViewClient.onPageFinished()方法通常需要等待很久才會(huì)回調(diào)(首次加載通常超過3s)青扔,這是因?yàn)閃ebView需要加載完一個(gè)網(wǎng)頁(yè)里主文檔和所有的資源才會(huì)回調(diào)這個(gè)方法。
      • 能不能在WebViewClient.onPageStarted()中注入呢既穆?答案是不確定。經(jīng)過測(cè)試雀鹃,有些機(jī)型可以幻工,有些機(jī)型不行。在WebViewClient.onPageStarted()中注入還有一個(gè)致命的問題——這個(gè)方法可能會(huì)回調(diào)多次黎茎,會(huì)造成js代碼的多次注入囊颅。
      • 從7.0開始,WebView加載js方式發(fā)生了一些小改變傅瞻,官方建議把js注入的時(shí)機(jī)放在頁(yè)面開始加載之后踢代。
    • 可以在onProgressChanged中方法中注入js代碼
      • 頁(yè)面的進(jìn)度加載到80%的時(shí)候,實(shí)際上dom樹已經(jīng)渲染得差不多了嗅骄,表明WebView已經(jīng)解析了<html>標(biāo)簽胳挎,這時(shí)候注入一般是成功的。
      • 提到的多次注入控制溺森,使用了boolean值變量控制慕爬;重新加載一個(gè)URL之前,需要重置boolean值變量屏积,讓重新加載后的頁(yè)面再次注入js

05.攔截緩存如何優(yōu)雅處理

  • WebView為何加載慢
    • webView是怎么加載網(wǎng)頁(yè)的呢医窿?
      • webView初始化->DOM下載→DOM解析→CSS請(qǐng)求+下載→CSS解析→渲染→繪制→合成
    • 渲染速度慢
      • 前端H5頁(yè)面渲染的速度取決于 兩個(gè)方面:
        • Js 解析效率。Js 本身的解析過程復(fù)雜炊林、解析速度不快 & 前端頁(yè)面涉及較多 JS 代碼文件姥卢,所以疊加起來會(huì)導(dǎo)致 Js 解析效率非常低
        • 手機(jī)硬件設(shè)備的性能。由于Android機(jī)型碎片化渣聚,這導(dǎo)致手機(jī)硬件設(shè)備的性能不可控独榴,而大多數(shù)的Android手機(jī)硬件設(shè)備無法達(dá)到很好很好的硬件性能
    • 頁(yè)面資源加載緩慢
      • H5 頁(yè)面從服務(wù)器獲得,并存儲(chǔ)在 Android手機(jī)內(nèi)存里:
        • H5頁(yè)面一般會(huì)比較多
        • 每加載一個(gè) H5頁(yè)面奕枝,都會(huì)產(chǎn)生較多網(wǎng)絡(luò)請(qǐng)求:
          • HTML 主 URL 自身的請(qǐng)求括眠;
          • HTML外部引用的JS、CSS倍权、字體文件掷豺,圖片也是一個(gè)獨(dú)立的 HTTP 請(qǐng)求
        • 每一個(gè)請(qǐng)求都串行的捞烟,這么多請(qǐng)求串起來,這導(dǎo)致 H5頁(yè)面資源加載緩慢
  • 解決WebView加載慢
    • 前端H5的緩存機(jī)制(WebView 自帶)
    • 資源攔截緩存
    • 資源攔截替換
  • webView瀏覽器緩存機(jī)制
    • 這些技術(shù)都是協(xié)議層所定義的当船,在Android的webView當(dāng)中我們可以通過配置決定是否采納這幾個(gè)協(xié)議的頭部屬性
    // LOAD_CACHE_ONLY: 不使用網(wǎng)絡(luò)题画,只讀取本地緩存數(shù)據(jù)
    // LOAD_DEFAULT: (默認(rèn))根據(jù)cache-control決定是否從網(wǎng)絡(luò)上取數(shù)據(jù)。
    // LOAD_NO_CACHE: 不使用緩存德频,只從網(wǎng)絡(luò)獲取數(shù)據(jù).
    // LOAD_CACHE_ELSE_NETWORK苍息,只要本地有,無論是否過期壹置,或者no-cache竞思,都使用緩存中的數(shù)據(jù)。
    ws.setCacheMode(WebSettings.LOAD_DEFAULT);
    
    • 一般設(shè)置為默認(rèn)的緩存模式就可以了钞护。關(guān)于緩存的配置, 主要還是靠web前端和后臺(tái)設(shè)置盖喷。關(guān)于瀏覽器緩存機(jī)制
  • 自身構(gòu)建緩存方案
    • 攔截處理
      • 在shouldInterceptRequest方法中攔截處理
      • 步驟1:判斷攔截資源的條件,即判斷url里的圖片資源的文件名
      • 步驟2:創(chuàng)建一個(gè)輸入流难咕,這里可以先從內(nèi)存中拿课梳,拿不到從磁盤中拿,再拿不到就從網(wǎng)絡(luò)獲取數(shù)據(jù)
      • 步驟3:打開需要替換的資源(存放在assets文件夾里)余佃,或者從lru中取出緩存的數(shù)據(jù)
      • 步驟4:替換資源
    • 有幾個(gè)問題
      • 如何判斷url中資源是否需要攔截暮刃,或者說是否需要緩存
      • 如何緩存js,css等
      • 緩存數(shù)據(jù)是否有時(shí)效性
      • 關(guān)于緩存下載的問題爆土,是引入okhttp還是原生網(wǎng)絡(luò)請(qǐng)求椭懊,緩存下載失敗該怎么處理
    • 在哪里進(jìn)行攔截
      • webView在加載網(wǎng)頁(yè)的時(shí)候,用戶能夠通過系統(tǒng)提供的API干預(yù)各個(gè)中間過程步势。我們要攔截的就是網(wǎng)頁(yè)資源請(qǐng)求的環(huán)節(jié)灾搏。這個(gè)過程,WebViewClient當(dāng)中提供了以下兩個(gè)入口:
        // android5.0以上的版本加入
        @Override
        public WebResourceResponse shouldInterceptRequest(WebView webView, WebResourceRequest webResourceRequest) {
          return super.shouldInterceptRequest(webView, webResourceRequest);
        }
        
        @Override
        public WebResourceResponse shouldInterceptRequest(WebView webView, String s) {
          return super.shouldInterceptRequest(webView, s);
        }
        
      • 替換資源操作
        • 只要在這兩個(gè)入口構(gòu)造正確的WebResourceResponse對(duì)象立润,就可以替換默認(rèn)的請(qǐng)求為我們提供的資源
        • 因此狂窑,在每次請(qǐng)求資源的時(shí)候根據(jù)請(qǐng)求的URL/WebResourceRequest判斷是否存在本地的緩存,并在緩存存在的情況下將緩存的輸入流返回

06.關(guān)于一些問題和優(yōu)化

  • 影響頁(yè)面加載的一些因素有那些桑腮?
    • 1.加載網(wǎng)頁(yè)中泉哈,如果圖片很多,而這些圖片的請(qǐng)求又是一個(gè)個(gè)獨(dú)立并且串行的請(qǐng)求破讨。那么可能會(huì)導(dǎo)致加載頁(yè)面比較緩慢……
    • 2.app原生和webView中請(qǐng)求丛晦,都會(huì)涉及到https的網(wǎng)絡(luò)請(qǐng)求,那么在請(qǐng)求前會(huì)有域名dns的解析提陶,這個(gè)也會(huì)有大約200毫秒的解析時(shí)間(主要耗費(fèi)時(shí)間dns烫沙,connection,服務(wù)器處理等)……
    • 3.webView加載html網(wǎng)頁(yè)時(shí)隙笆,有些js一直在執(zhí)行比如動(dòng)畫之類的東西锌蓄,此刻webView掛在了后臺(tái)這些資源是不會(huì)被釋放用戶也無法感知升筏。導(dǎo)致耗費(fèi)資源……
    • 4.關(guān)于加載loading或者加載進(jìn)度條,不一定要放到onPageStarted開始執(zhí)行即顯示出來瘸爽,因?yàn)閣ebView從創(chuàng)建到這個(gè)方法會(huì)有一個(gè)時(shí)間……
    • 5.webView默認(rèn)開啟密碼保存功能您访,如果網(wǎng)頁(yè)涉及到用戶登陸,密碼會(huì)被明文保到 /data/data/com.package.name/databases/webview.db 中剪决,這樣就有被盜取密碼的危險(xiǎn)……
    • 6.h5頁(yè)面被攔截或者注入廣告灵汪,重定向,或者DNS劫持柑潦。一般跟連接的wifi有關(guān)系(http劫持)享言,也可能跟運(yùn)營(yíng)商有關(guān)系(dns劫持)
  • 具體可以操作的優(yōu)化分析
    • 1.加載webView中的資源時(shí),針對(duì)圖片渗鬼,等頁(yè)面finish后再發(fā)起圖片加載(也就是執(zhí)行onPageFinished設(shè)置加載圖片)览露。具體看5.0.2圖片加載次序優(yōu)化
    • 2.DNS域名解析采用和客戶端API相同的域名, DNS會(huì)在系統(tǒng)級(jí)別進(jìn)行緩存乍钻,對(duì)于WebView的地址肛循,如果使用的域名與native的API相同铭腕,則可以直接使用緩存的DNS而不用再發(fā)起請(qǐng)求圖片银择。具體看5.0.7 DNS采用和客戶端API相同的域名
    • 3.在后臺(tái)的時(shí)候,會(huì)調(diào)用onStop方法累舷,即此時(shí)關(guān)閉js交互浩考,回到前臺(tái)調(diào)用onResume再開啟js交互。具體看5.0.9 后臺(tái)無法釋放js導(dǎo)致發(fā)熱耗電
    • 4.提前顯示進(jìn)度條不是提升性能被盈,但是對(duì)用戶體驗(yàn)來說也是很重要的一點(diǎn) 析孽,WebView.loadUrl("url") 不會(huì)立馬就回調(diào)onPageStarted方法,因?yàn)樵谶@一時(shí)間段只怎,WebView 有可能在初始化內(nèi)核袜瞬,也有可能在與服務(wù)器建立連接,這個(gè)時(shí)間段容易出現(xiàn)白屏
    • 5.需要通過 WebSettings.setSavePassword(false) 關(guān)閉密碼保存功能身堡。
    • 6.一般可以處理:1使用https代替http邓尤;2.添加白名單(比如添加自己網(wǎng)站的host,其他不給訪問)贴谎;3.對(duì)頁(yè)面md5校驗(yàn)(不太好)汞扎。設(shè)置白名單參考:5.0.8 如何設(shè)置白名單操作
  • 還有一些其他的優(yōu)化小細(xì)節(jié)
    • a.WebView處理404、500邏輯擅这,在WebChromeClient子類中可以重寫他的onReceivedTitle()方法監(jiān)聽標(biāo)題澈魄,還有在WebChromeClient子類中onReceivedHttpError可以監(jiān)聽statusCode。具體操作看5.1.5 WebView處理404仲翎、500邏輯
    • b.如果不顯示圖片痹扇,開發(fā)的時(shí)候可能使用的是https的鏈接, 但是鏈接中的圖片可能是http的铛漓,需要開啟設(shè)置。具體看:4.1.4 webView加載網(wǎng)頁(yè)不顯示圖片
    • c.evaluateJavascript(String var1, ValueCallback<String> var2)中url長(zhǎng)度有限制帘营,在19以上超過2097152個(gè)字符失效票渠,這個(gè)地方可以加個(gè)判斷。不過一般很難碰到……具體可以參考:4.3.1 Android與js傳遞數(shù)據(jù)大小有限制
    • d.在web頁(yè)面android軟鍵盤覆蓋問題芬迄,常見的有android:windowSoftInputMode的值adjustPan或者adjustResize即可问顷,如果webView是全屏模式則仍然會(huì)出現(xiàn)問題。具體看:4.6.1 在web頁(yè)面android軟鍵盤覆蓋問題
    • e.關(guān)于WebView隱藏H5頁(yè)面中的某個(gè)標(biāo)簽視圖禀梳,大概操作就是在頁(yè)面加載完成杜窄,通過getElementsByClassName找到h5中標(biāo)簽name,然后手動(dòng)寫function方法隱藏標(biāo)簽算途。但加載時(shí)機(jī)很關(guān)鍵塞耕,不過會(huì)造成閃屏和多次加載。具體看:4.6.6 WebView如何隱藏H5的部分內(nèi)容問題
    • f.頁(yè)面重定向嘴瓤,會(huì)導(dǎo)致onPageStarted多次執(zhí)行扫外,那么這個(gè)時(shí)候如何避免加載進(jìn)度條出現(xiàn)執(zhí)行多次,或者跳動(dòng)的問題廓脆。具體可見:09.web進(jìn)度條避免多次加載
    • g.建議開啟Google安全瀏覽服務(wù)筛谚,用戶訪問不安全網(wǎng)頁(yè)會(huì)提示安全問題;webView使用上的建議設(shè)置布局高度和寬度設(shè)置為 match_parent停忿;具體可見48.開啟Google安全瀏覽服務(wù)

07.關(guān)于一點(diǎn)面向?qū)ο蟮乃枷?/h3>
  • 針對(duì)webView視頻播放演變
    • 1.最剛開始把視頻全屏show和hide的邏輯都放到X5WebChromeClient中處理驾讲,相當(dāng)于這個(gè)類中邏輯比較多
    • 2.后期把視頻全屏播放邏輯都抽到了VideoWebChromeClient類中處理,這樣只需要繼承該類即可席赂。這個(gè)類獨(dú)立吮铭,拿來即用。
    • 3.后期演變颅停,一個(gè)視頻全屏播放接口 + 接口實(shí)現(xiàn)類 + VideoChromeClient谓晌,接口主要能夠解耦
  • 關(guān)于webView攔截緩存處理
    • 1.代碼結(jié)構(gòu)大概是:攔截緩存接口 + 接口實(shí)現(xiàn)類 + 接口委派類
    • 2.優(yōu)點(diǎn):委派類和實(shí)現(xiàn)類解耦;便于增加過濾功能(比如用了https+dns優(yōu)化就不用攔截緩存)癞揉;
    //1.創(chuàng)建委托對(duì)象
    WebViewCacheDelegate webViewCacheDelegate = WebViewCacheDelegate.getInstance();
    //2.通過委托對(duì)象調(diào)用方法
    WebResourceResponse webResourceResponse = webViewCacheDelegate.interceptRequest(url);
    
  • 關(guān)于shouldOverrideUrlLoading處理多類型
    • 比如:封裝庫(kù)中需要處理打電話纸肉,發(fā)短信,發(fā)郵件烧董,地圖定位毁靶,圖片,超鏈接等攔截邏輯
    • 最剛開始是把處理的邏輯都放到了WebViewClient中的shouldOverrideUrlLoading方法中處理逊移。不過發(fā)現(xiàn)這個(gè)類代碼越來越多……
    • 后期演變预吆,針對(duì)電話短信等將處理邏輯抽取到WebSchemeIntent類中,針對(duì)圖片處理邏輯抽取到SaveImageProcessor類中胳泉。具體看WebSchemeIntent
    • 這樣做拐叉,相當(dāng)于保證了類的單一性職責(zé)岩遗,即類盡量保證內(nèi)部處理的功能盡可能單一,而不是錯(cuò)綜復(fù)雜……

08.關(guān)于后期需要研究的目標(biāo)

  • 目標(biāo)
    • web頁(yè)面特別消耗流量凤瘦,每次打開頁(yè)面都會(huì)請(qǐng)求網(wǎng)絡(luò)宿礁,建議對(duì)流量的消耗進(jìn)行優(yōu)化……除了對(duì)lib庫(kù)中對(duì)攔截做OkHttp緩存,還有什么其他方案
  • web頁(yè)面涉及流量的幾個(gè)方面
    • 普通https請(qǐng)求蔬芥,一般過程是服務(wù)端(對(duì)象)-->網(wǎng)絡(luò)中(二進(jìn)制流)-->客戶端(對(duì)象)梆靖,文本內(nèi)容會(huì)做傳輸壓縮
    • 網(wǎng)絡(luò)圖片下載,圖片下載消耗的流量較多
    • h5頁(yè)面展示笔诵,由于h5頁(yè)面是交由前端處理顯示返吻,客戶端開發(fā)關(guān)注的少些,而此處消耗了大量的流量
  • 如何查看web頁(yè)面消耗流量
    • 使用TrafficStats即可查看流量的消耗

09.開源庫(kù)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乎婿,一起剝皮案震驚了整個(gè)濱河市测僵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谢翎,老刑警劉巖捍靠,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異森逮,居然都是意外死亡榨婆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門吊宋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來纲辽,“玉大人颜武,你說我怎么就攤上這事璃搜。” “怎么了鳞上?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵这吻,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我篙议,道長(zhǎng)唾糯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任鬼贱,我火速辦了婚禮移怯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘这难。我一直安慰自己舟误,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布姻乓。 她就那樣靜靜地躺著嵌溢,像睡著了一般眯牧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赖草,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天学少,我揣著相機(jī)與錄音,去河邊找鬼秧骑。 笑死版确,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的乎折。 我是一名探鬼主播阀坏,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼笆檀!你這毒婦竟也來了忌堂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤酗洒,失蹤者是張志新(化名)和其女友劉穎士修,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體樱衷,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡棋嘲,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了矩桂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沸移。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖侄榴,靈堂內(nèi)的尸體忽然破棺而出雹锣,到底是詐尸還是另有隱情,我是刑警寧澤癞蚕,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布蕊爵,位于F島的核電站,受9級(jí)特大地震影響桦山,放射性物質(zhì)發(fā)生泄漏攒射。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一恒水、第九天 我趴在偏房一處隱蔽的房頂上張望会放。 院中可真熱鬧,春花似錦钉凌、人聲如沸咧最。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)窗市。三九已至先慷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間咨察,已是汗流浹背论熙。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留摄狱,地道東北人脓诡。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像媒役,于是被迫代替她去往敵國(guó)和親祝谚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355