目錄介紹
- 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
- 在代碼中通過loadUrl加載百度的首頁(yè),此時(shí)的行為屬于(B)方式唤冈。
- 得出結(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)
- 1.如果是目的地址,那么方法的執(zhí)行順序是:
- 在(B)行為下:
- 1.如果是目的地址淳梦,那么方法的執(zhí)行順序是:
- onPageStarted()-> onPageFinished()
- loadUrl()加載地址時(shí),一般不會(huì)觸發(fā)shouldOverrideUrlLoading()昔字,一旦觸發(fā)了爆袍,就說明這是一個(gè)重定向地址。
- 2.如果是重定向地址,方法的執(zhí)行順序就是:
- fixed position -> … -> fixed position -> onPageStarted() -> onPageFinished()
- 1.如果是目的地址淳梦,那么方法的執(zhí)行順序是:
- 在(A)行為方式下(用戶點(diǎn)擊鏈接的回調(diào)):
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í)行多次
- 常見的解決方案
- 手動(dòng)管理回退棧,遇到重定向時(shí)回退兩次累驮。
- 通過HitTestResult判斷是否是重定向酣倾,從而決定是否自己加載url。具體看:16.301/302回退棧問題解決方案2
- 通過設(shè)置標(biāo)記位谤专,在onPageStarted和onPageFinished分別標(biāo)記變量避免重定向躁锡。具體看:17.301/302回退棧問題解決方案3
- 通過用戶的touch事件來判斷重定向。具體看:15.301/302回退棧如何處理1
- 如何判斷重定向
- 通過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坝辫。即可解決回退問題篷就。
- 具體方法思路
- 可以看:20.重定向終極優(yōu)雅解決方案
- 具體代碼看:X5WebViewClient
- 需要準(zhǔn)備的條件
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()
- Java調(diào)用js方法有兩種:
- 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
- onPageFinished()或者onPageStarted()方法中注入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á)到很好很好的硬件性能
- 前端H5頁(yè)面渲染的速度取決于 兩個(gè)方面:
- 頁(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è)面資源加載緩慢
- H5 頁(yè)面從服務(wù)器獲得,并存儲(chǔ)在 Android手機(jī)內(nèi)存里:
- webView是怎么加載網(wǎng)頁(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判斷是否存在本地的緩存,并在緩存存在的情況下將緩存的輸入流返回
- webView在加載網(wǎng)頁(yè)的時(shí)候,用戶能夠通過系統(tǒng)提供的API干預(yù)各個(gè)中間過程步势。我們要攔截的就是網(wǎng)頁(yè)資源請(qǐng)求的環(huán)節(jié)灾搏。這個(gè)過程,WebViewClient當(dāng)中提供了以下兩個(gè)入口:
- 攔截處理
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ù)
- 1.最剛開始把視頻全屏show和hide的邏輯都放到X5WebChromeClient中處理驾讲,相當(dāng)于這個(gè)類中邏輯比較多
- 2.后期把視頻全屏播放邏輯都抽到了VideoWebChromeClient類中處理,這樣只需要繼承該類即可席赂。這個(gè)類獨(dú)立吮铭,拿來即用。
- 3.后期演變颅停,一個(gè)視頻全屏播放接口 + 接口實(shí)現(xiàn)類 + VideoChromeClient谓晌,接口主要能夠解耦
- 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);
- 比如:封裝庫(kù)中需要處理打電話纸肉,發(fā)短信,發(fā)郵件烧董,地圖定位毁靶,圖片,超鏈接等攔截邏輯
- 最剛開始是把處理的邏輯都放到了WebViewClient中的shouldOverrideUrlLoading方法中處理逊移。不過發(fā)現(xiàn)這個(gè)類代碼越來越多……
- 后期演變预吆,針對(duì)電話短信等將處理邏輯抽取到WebSchemeIntent類中,針對(duì)圖片處理邏輯抽取到SaveImageProcessor類中胳泉。具體看WebSchemeIntent
- 這樣做拐叉,相當(dāng)于保證了類的單一性職責(zé)岩遗,即類盡量保證內(nèi)部處理的功能盡可能單一,而不是錯(cuò)綜復(fù)雜……
- web頁(yè)面特別消耗流量凤瘦,每次打開頁(yè)面都會(huì)請(qǐng)求網(wǎng)絡(luò)宿礁,建議對(duì)流量的消耗進(jìn)行優(yōu)化……除了對(duì)lib庫(kù)中對(duì)攔截做OkHttp緩存,還有什么其他方案
- 普通https請(qǐng)求蔬芥,一般過程是服務(wù)端(對(duì)象)-->網(wǎng)絡(luò)中(二進(jìn)制流)-->客戶端(對(duì)象)梆靖,文本內(nèi)容會(huì)做傳輸壓縮
- 網(wǎng)絡(luò)圖片下載,圖片下載消耗的流量較多
- h5頁(yè)面展示笔诵,由于h5頁(yè)面是交由前端處理顯示返吻,客戶端開發(fā)關(guān)注的少些,而此處消耗了大量的流量
- 使用TrafficStats即可查看流量的消耗