目錄介紹
- 01.loadUrl到底做了什么
- 02.觸發(fā)加載網(wǎng)頁的行為
- 03.webView重定向怎么辦
- 04.js交互的一點知識分享
- 05.攔截緩存如何優(yōu)雅處理
- 06.關(guān)于一些問題和優(yōu)化
- 07.關(guān)于一點面向?qū)ο笏枷?/li>
- 08.關(guān)于后期需要研究目標
01.loadUrl到底做了什么
- WebView.loadUrl(url)加載網(wǎng)頁做了什么?
- 加載網(wǎng)頁是一個復雜的過程,在這個過程中,我們可能需要執(zhí)行一些操作,包括:
- 加載網(wǎng)頁前,重置WebView狀態(tài)以及與業(yè)務(wù)綁定的變量狀態(tài)。WebView狀態(tài)包括重定向狀態(tài)(mTouchByUser)、前端控制的回退棧(mBackStep)等,業(yè)務(wù)狀態(tài)包括進度條、當前頁的分享內(nèi)容、分享按鈕的顯示隱藏等。
- 加載網(wǎng)頁前,根據(jù)不同的域拼接本地客戶端的參數(shù),包括基本的機型信息、版本信息、登錄信息以及埋點使用的Refer信息等,有時候涉及交易、財產(chǎn)等還需要做額外的配置。
- 開始執(zhí)行頁面加載操作時,會回調(diào)WebViewClient.onPageStarted(webView,url,favicon)。在此方法中,可以重置重定向保護的變量(mRedirectProtected),當然也可以在頁面加載前重置,由于歷史遺留代碼問題,此處尚未省去優(yōu)化。
- 加載頁面的過程中回調(diào)哪些方法?
- WebChromeClient.onReceivedTitle(webview, title),用來設(shè)置標題。需要注意的是,在部分Android系統(tǒng)版本中可能會回調(diào)多次這個方法,而且有時候回調(diào)的title是一個url,客戶端可以針對這種情況進行特殊處理,避免在標題欄顯示不必要的鏈接。
- WebChromeClient.onProgressChanged(webview, progress),根據(jù)這個回調(diào),可以控制進度條的進度(包括顯示與隱藏)。一般情況下,想要達到100%的進度需要的時間較長(特別是首次加載),用戶長時間等待進度條不消失必定會感到焦慮,影響體驗。其實當progress達到80的時候,加載出來的頁面已經(jīng)基本可用了。事實上,國內(nèi)廠商大部分都會提前隱藏進度條,讓用戶以為網(wǎng)頁加載很快。
- WebViewClient.shouldInterceptRequest(webview, request),無論是普通的頁面請求(使用GET/POST),還是頁面中的異步請求,或者頁面中的資源請求,都會回調(diào)這個方法,給開發(fā)一次攔截請求的機會。在這個方法中,我們可以進行靜態(tài)資源的攔截并使用緩存數(shù)據(jù)代替,也可以攔截頁面,使用自己的網(wǎng)絡(luò)框架來請求數(shù)據(jù)。包括后面介紹的WebView免流方案,也和此方法有關(guān)。
- WebViewClient.shouldOverrideUrlLoading(webview, request),如果遇到了重定向,或者點擊了頁面中的a標簽實現(xiàn)頁面跳轉(zhuǎn),那么會回調(diào)這個方法??梢哉f這個是WebView里面最重要的回調(diào)之一,后面WebView與Native頁面交互一節(jié)將會詳細介紹這個方法。
- WebViewClient.onReceivedError(webview,handler,error),加載頁面的過程中發(fā)生了錯誤,會回調(diào)這個方法。主要是http錯誤以及ssl錯誤。在這兩個回調(diào)中,我們可以進行異常上報,監(jiān)控異常頁面、過期頁面,及時反饋給運營或前端修改。在處理ssl錯誤時,遇到不信任的證書可以進行特殊處理,例如對域名進行判斷,針對自己公司的域名“放行”,防止進入丑陋的錯誤證書頁面。也可以與Chrome一樣,彈出ssl證書疑問彈窗,給用戶選擇的余地。
- 加載頁面結(jié)束回調(diào)哪些方法
- 會回調(diào)WebViewClient.onPageFinished(webview,url)。
- 這時候可以根據(jù)回退棧的情況判斷是否顯示關(guān)閉WebView按鈕。通過mActivityWeb.canGoBackOrForward(-1)判斷是否可以回退。
02.觸發(fā)加載網(wǎng)頁的行為
- 觸發(fā)加載網(wǎng)頁的行為主要有兩種方式:
- (A)點擊頁面,觸發(fā)<link>標簽。
- (B)調(diào)用WebView的loadUrl()方法
- 這兩種方法都會發(fā)出一條地址,區(qū)別就在于這條地址是目的地址還是重定向地址。以訪問http://www.baidu.com百度的頁面來測試一下方法的執(zhí)行順序。
- 觸發(fā)加載網(wǎng)頁流程分析
- 在代碼中通過loadUrl加載百度的首頁,此時的行為屬于(B)方式。
- 可以發(fā)現(xiàn)大概的執(zhí)行順序是:onPageStarted ——> shouldOverrideUrlLoading ——> onPageFinished
- 那么為什么會執(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 - 在首頁,點擊一下“hao123”,跳轉(zhuǎn)到www.hao123.com的主頁上來,此時的行為屬于(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導航-上網(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ōu)酷網(wǎng)進行跳轉(zhuǎn),此時的行為屬于(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)酷視頻-首頁 X5LogUtils: -------onPageFinished-------https://www.youku.com/ - 然后從優(yōu)酷頁面回退到hao123頁面,看看又回執(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導航-上網(wǎng)從這里開始 X5LogUtils: -------onReceivedTitle-------hao123導航-上網(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頁面回退到百度首頁,看看又回執(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加載百度的首頁,此時的行為屬于(B)方式。
- 得出結(jié)論分析說明
- 在(A)行為方式下(用戶點擊鏈接的回調(diào)):
- 1.如果是目的地址,那么方法的執(zhí)行順序是:
- shouldOverrideUrlLoading() -> onPageStarted()-> onPageFinished()
- shouldOverrideUrlLoading()由于它要提供給APP選擇加載網(wǎng)頁環(huán)境的機會,所以只要是網(wǎng)頁上地址請求,都會獲取到。
- 2.如果是重定向地址,在跳轉(zhuǎn)到目的地址之前會進行不斷的地址定位,每一次地址定位都會由以下執(zhí)行順序體現(xiàn)出來:
- onPageStarted()->shouldOverrideUrlLoading()->onPageFinished()
- 暫且設(shè)定這種執(zhí)行順序叫:fixed position
- 那么一個正常的重定向地址,方法的執(zhí)行順序就是:
- shouldOverrideUrlLoading() -> fixed position -> … -> fixed position -> onPageStarted() -> onPageFinished()
- 舉個例子:有重定向(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()加載地址時,一般不會觸發(fā)shouldOverrideUrlLoading(),一旦觸發(fā)了,就說明這是一個重定向地址。
- 2.如果是重定向地址,方法的執(zhí)行順序就是:
- fixed position -> … -> fixed position -> onPageStarted() -> onPageFinished()
- 1.如果是目的地址,那么方法的執(zhí)行順序是:
- 在(A)行為方式下(用戶點擊鏈接的回調(diào)):
03.webView重定向怎么辦
- webView出現(xiàn)302/303重定向
- 302重定向又稱之為302代表暫時性轉(zhuǎn)移,比如你跳轉(zhuǎn)A頁面,但由于網(wǎng)頁添加了約束條件,可能讓你跳轉(zhuǎn)到B頁面,甚至多次重定向。
- 導致的問題
- 1.A-->B-->C,比如你跳轉(zhuǎn)A頁面,最終重定向到C頁面。這個時候調(diào)用goBack方法,返回到B鏈接,但是B鏈接又會跳轉(zhuǎn)到C鏈接,從而導致沒法返回到A鏈接界面
- 2.會多次執(zhí)行onPageStarted和onPageFinished,如果你這里有加載進度條或者loading,那么會導致進度條或者loading執(zhí)行多次
- 常見的解決方案
- 手動管理回退棧,遇到重定向時回退兩次。
- 通過HitTestResult判斷是否是重定向,從而決定是否自己加載url。具體看:16.301/302回退棧問題解決方案2
- 通過設(shè)置標記位,在onPageStarted和onPageFinished分別標記變量避免重定向。具體看:17.301/302回退棧問題解決方案3
- 通過用戶的touch事件來判斷重定向。具體看:15.301/302回退棧如何處理1
- 如何判斷重定向
- 通過getHitTestResult()返回值,如果返回null,或者UNKNOWN_TYPE,則表示為重定向。具體看:18.如何用代碼判斷是否重定向
- 在加載一個頁面開始的時候會回調(diào)onPageStarted方法,在該頁面加載完成之后會回調(diào)onPageFinished方法。而如果該鏈接發(fā)生了重定向,回調(diào)shouldOverrideUrlLoading會在回調(diào)onPageFinished之前。
- 終極解決方案如下
- 需要準備的條件
- 創(chuàng)建一個棧,主要是用來存取和移除url的操作。這個url包括所有的請求鏈接
- 定義一個變量,用于判斷頁面是否處于正在加載中。
- 定義一個變量,用于記錄重定向前的鏈接url
- 定一個重定向時間間隔,主要為了避免刷新造成循環(huán)重定向
- 具體怎么操作呢
- 在執(zhí)行onPageStarted時,先移除棧中上一個url,然后將url加載到棧中。
- 當出現(xiàn)錯誤重定向的時候,如果和上一次重定向的時間間隔大于3秒,則reload頁面。
- 在回退操作的時候,判斷如果可以回退,則從棧中獲取最后停留的url,然后loadUrl。即可解決回退問題。
- 具體方法思路
- 可以看:20.重定向終極優(yōu)雅解決方案
- 具體代碼看:X5WebViewClient
- 需要準備的條件
04.js交互的一點知識分享
- 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 方法進行添加對象映射。js最終通過對象調(diào)用原生方法
- 2.shouldOverrideUrlLoading攔截操作,獲取scheme匹配,與網(wǎng)頁約定好一個協(xié)議,如果匹配,執(zhí)行相應操作
- 3.利用WebChromeClient回調(diào)接口onJsPrompt攔截操作。
- onJsAlert 是不能返回值的,而 onJsConfirm 只能夠返回確定或者取消兩個值,只有 onJsPrompt 方法是可以返回字符串類型的值,操作最全面方便。
- 詳細分析可以看:03.Js調(diào)用Android
- js調(diào)用java原生方法可能存在的問題?
- 提出問題
- 1.原生方法是否可以執(zhí)行耗時操作,如果有會阻塞通信嗎?4.4.8 prompt的一個坑導致js掛掉
- 2.多線程中調(diào)用多個原生方法,如何保證原生方法每一個都會被執(zhí)行到?
- 3.js會阻塞等待當前原生函數(shù)(耗時操作的那個)執(zhí)行完畢再往下走,所以js調(diào)用java方法里面最好也不要做耗時操作
- 解決方案
- 1.在js調(diào)用?window.alert?,?window.confirm?,?window.prompt?時,?會調(diào)用WebChromeClient?對應方法,可以此為入口,作為消息傳遞通道,考慮到開發(fā)習慣,一般不會選擇alert跟confirm,?通常會選prompt作為入口,在App中就是onJsPrompt作為jsbridge的調(diào)用入口。由于onJsPrompt是在UI線程執(zhí)行,所以盡量不要做耗時操作,可以借助Handler靈活處理。
- 2.利用Handler封裝一下,讓每個任務(wù)自己處理,耗時的話就開線程自己處理。具體可以看:WvWebView
- 提出問題
- java調(diào)用js的時機
- onPageFinished()或者onPageStarted()方法中注入js代碼嗎?
- js交互,大部分都會認為js在WebViewClient.onPageFinished()方法中注入最合適,此時dom樹已經(jīng)構(gòu)建完成,頁面已經(jīng)完全展現(xiàn)出來。但如果做過頁面加載速度的測試,會發(fā)現(xiàn)WebViewClient.onPageFinished()方法通常需要等待很久才會回調(diào)(首次加載通常超過3s),這是因為WebView需要加載完一個網(wǎng)頁里主文檔和所有的資源才會回調(diào)這個方法。
- 能不能在WebViewClient.onPageStarted()中注入呢?答案是不確定。經(jīng)過測試,有些機型可以,有些機型不行。在WebViewClient.onPageStarted()中注入還有一個致命的問題——這個方法可能會回調(diào)多次,會造成js代碼的多次注入。
- 從7.0開始,WebView加載js方式發(fā)生了一些小改變,官方建議把js注入的時機放在頁面開始加載之后。
- 可以在onProgressChanged中方法中注入js代碼
- 頁面的進度加載到80%的時候,實際上dom樹已經(jīng)渲染得差不多了,表明WebView已經(jīng)解析了<html>標簽,這時候注入一般是成功的。
- 提到的多次注入控制,使用了boolean值變量控制;重新加載一個URL之前,需要重置boolean值變量,讓重新加載后的頁面再次注入js
- onPageFinished()或者onPageStarted()方法中注入js代碼嗎?
05.攔截緩存如何優(yōu)雅處理
- WebView為何加載慢
- webView是怎么加載網(wǎng)頁的呢?
- webView初始化->DOM下載→DOM解析→CSS請求+下載→CSS解析→渲染→繪制→合成
- 渲染速度慢
- 前端H5頁面渲染的速度取決于 兩個方面:
- Js 解析效率。Js 本身的解析過程復雜、解析速度不快 & 前端頁面涉及較多 JS 代碼文件,所以疊加起來會導致 Js 解析效率非常低
- 手機硬件設(shè)備的性能。由于Android機型碎片化,這導致手機硬件設(shè)備的性能不可控,而大多數(shù)的Android手機硬件設(shè)備無法達到很好很好的硬件性能
- 前端H5頁面渲染的速度取決于 兩個方面:
- 頁面資源加載緩慢
- H5 頁面從服務(wù)器獲得,并存儲在 Android手機內(nèi)存里:
- H5頁面一般會比較多
- 每加載一個 H5頁面,都會產(chǎn)生較多網(wǎng)絡(luò)請求:
- HTML 主 URL 自身的請求;
- HTML外部引用的JS、CSS、字體文件,圖片也是一個獨立的 HTTP 請求
- 每一個請求都串行的,這么多請求串起來,這導致 H5頁面資源加載緩慢
- H5 頁面從服務(wù)器獲得,并存儲在 Android手機內(nèi)存里:
- webView是怎么加載網(wǎng)頁的呢?
- 解決WebView加載慢
- 前端H5的緩存機制(WebView 自帶)
- 資源攔截緩存
- 資源攔截替換
- webView瀏覽器緩存機制
- 這些技術(shù)都是協(xié)議層所定義的,在Android的webView當中我們可以通過配置決定是否采納這幾個協(xié)議的頭部屬性
// LOAD_CACHE_ONLY: 不使用網(wǎng)絡(luò),只讀取本地緩存數(shù)據(jù) // LOAD_DEFAULT: (默認)根據(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è)置為默認的緩存模式就可以了。關(guān)于緩存的配置, 主要還是靠web前端和后臺設(shè)置。關(guān)于瀏覽器緩存機制
- 自身構(gòu)建緩存方案
- 攔截處理
- 在shouldInterceptRequest方法中攔截處理
- 步驟1:判斷攔截資源的條件,即判斷url里的圖片資源的文件名
- 步驟2:創(chuàng)建一個輸入流,這里可以先從內(nèi)存中拿,拿不到從磁盤中拿,再拿不到就從網(wǎng)絡(luò)獲取數(shù)據(jù)
- 步驟3:打開需要替換的資源(存放在assets文件夾里),或者從lru中取出緩存的數(shù)據(jù)
- 步驟4:替換資源
- 有幾個問題
- 如何判斷url中資源是否需要攔截,或者說是否需要緩存
- 如何緩存js,css等
- 緩存數(shù)據(jù)是否有時效性
- 關(guān)于緩存下載的問題,是引入okhttp還是原生網(wǎng)絡(luò)請求,緩存下載失敗該怎么處理
- 在哪里進行攔截
- webView在加載網(wǎng)頁的時候,用戶能夠通過系統(tǒng)提供的API干預各個中間過程。我們要攔截的就是網(wǎng)頁資源請求的環(huán)節(jié)。這個過程,WebViewClient當中提供了以下兩個入口:
// 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òu)造正確的WebResourceResponse對象,就可以替換默認的請求為我們提供的資源
- 因此,在每次請求資源的時候根據(jù)請求的URL/WebResourceRequest判斷是否存在本地的緩存,并在緩存存在的情況下將緩存的輸入流返回
- webView在加載網(wǎng)頁的時候,用戶能夠通過系統(tǒng)提供的API干預各個中間過程。我們要攔截的就是網(wǎng)頁資源請求的環(huán)節(jié)。這個過程,WebViewClient當中提供了以下兩個入口:
- 攔截處理
06.關(guān)于一些問題和優(yōu)化
- 影響頁面加載的一些因素有那些?
- 1.加載網(wǎng)頁中,如果圖片很多,而這些圖片的請求又是一個個獨立并且串行的請求。那么可能會導致加載頁面比較緩慢……
- 2.app原生和webView中請求,都會涉及到https的網(wǎng)絡(luò)請求,那么在請求前會有域名dns的解析,這個也會有大約200毫秒的解析時間(主要耗費時間dns,connection,服務(wù)器處理等)……
- 3.webView加載html網(wǎng)頁時,有些js一直在執(zhí)行比如動畫之類的東西,此刻webView掛在了后臺這些資源是不會被釋放用戶也無法感知。導致耗費資源……
- 4.關(guān)于加載loading或者加載進度條,不一定要放到onPageStarted開始執(zhí)行即顯示出來,因為webView從創(chuàng)建到這個方法會有一個時間……
- 5.webView默認開啟密碼保存功能,如果網(wǎng)頁涉及到用戶登陸,密碼會被明文保到 /data/data/com.package.name/databases/webview.db 中,這樣就有被盜取密碼的危險……
- 6.h5頁面被攔截或者注入廣告,重定向,或者DNS劫持。一般跟連接的wifi有關(guān)系(http劫持),也可能跟運營商有關(guān)系(dns劫持)
- 具體可以操作的優(yōu)化分析
- 1.加載webView中的資源時,針對圖片,等頁面finish后再發(fā)起圖片加載(也就是執(zhí)行onPageFinished設(shè)置加載圖片)。具體看5.0.2圖片加載次序優(yōu)化
- 2.DNS域名解析采用和客戶端API相同的域名, DNS會在系統(tǒng)級別進行緩存,對于WebView的地址,如果使用的域名與native的API相同,則可以直接使用緩存的DNS而不用再發(fā)起請求圖片。具體看5.0.7 DNS采用和客戶端API相同的域名
- 3.在后臺的時候,會調(diào)用onStop方法,即此時關(guān)閉js交互,回到前臺調(diào)用onResume再開啟js交互。具體看5.0.9 后臺無法釋放js導致發(fā)熱耗電
- 4.提前顯示進度條不是提升性能,但是對用戶體驗來說也是很重要的一點 ,WebView.loadUrl("url") 不會立馬就回調(diào)onPageStarted方法,因為在這一時間段,WebView 有可能在初始化內(nèi)核,也有可能在與服務(wù)器建立連接,這個時間段容易出現(xiàn)白屏
- 5.需要通過 WebSettings.setSavePassword(false) 關(guān)閉密碼保存功能。
- 6.一般可以處理:1使用https代替http;2.添加白名單(比如添加自己網(wǎng)站的host,其他不給訪問);3.對頁面md5校驗(不太好)。設(shè)置白名單參考:5.0.8 如何設(shè)置白名單操作
- 還有一些其他的優(yōu)化小細節(jié)
- a.WebView處理404、500邏輯,在WebChromeClient子類中可以重寫他的onReceivedTitle()方法監(jiān)聽標題,還有在WebChromeClient子類中onReceivedHttpError可以監(jiān)聽statusCode。具體操作看5.1.5 WebView處理404、500邏輯
- b.如果不顯示圖片,開發(fā)的時候可能使用的是https的鏈接, 但是鏈接中的圖片可能是http的,需要開啟設(shè)置。具體看:4.1.4 webView加載網(wǎng)頁不顯示圖片
- c.evaluateJavascript(String var1, ValueCallback<String> var2)中url長度有限制,在19以上超過2097152個字符失效,這個地方可以加個判斷。不過一般很難碰到……具體可以參考:4.3.1 Android與js傳遞數(shù)據(jù)大小有限制
- d.在web頁面android軟鍵盤覆蓋問題,常見的有android:windowSoftInputMode的值adjustPan或者adjustResize即可,如果webView是全屏模式則仍然會出現(xiàn)問題。具體看:4.6.1 在web頁面android軟鍵盤覆蓋問題
- e.關(guān)于WebView隱藏H5頁面中的某個標簽視圖,大概操作就是在頁面加載完成,通過getElementsByClassName找到h5中標簽name,然后手動寫function方法隱藏標簽。但加載時機很關(guān)鍵,不過會造成閃屏和多次加載。具體看:4.6.6 WebView如何隱藏H5的部分內(nèi)容問題
- f.頁面重定向,會導致onPageStarted多次執(zhí)行,那么這個時候如何避免加載進度條出現(xiàn)執(zhí)行多次,或者跳動的問題。具體可見:09.web進度條避免多次加載
- g.建議開啟Google安全瀏覽服務(wù),用戶訪問不安全網(wǎng)頁會提示安全問題;webView使用上的建議設(shè)置布局高度和寬度設(shè)置為 match_parent;具體可見48.開啟Google安全瀏覽服務(wù)
07.關(guān)于一點面向?qū)ο蟮乃枷?/h3>
- 針對webView視頻播放演變
- 1.最剛開始把視頻全屏show和hide的邏輯都放到X5WebChromeClient中處理,相當于這個類中邏輯比較多
- 2.后期把視頻全屏播放邏輯都抽到了VideoWebChromeClient類中處理,這樣只需要繼承該類即可。這個類獨立,拿來即用。
- 3.后期演變,一個視頻全屏播放接口 + 接口實現(xiàn)類 + VideoChromeClient,接口主要能夠解耦
- 關(guān)于webView攔截緩存處理
- 1.代碼結(jié)構(gòu)大概是:攔截緩存接口 + 接口實現(xiàn)類 + 接口委派類
- 2.優(yōu)點:委派類和實現(xiàn)類解耦;便于增加過濾功能(比如用了https+dns優(yōu)化就不用攔截緩存);
//1.創(chuàng)建委托對象
WebViewCacheDelegate webViewCacheDelegate = WebViewCacheDelegate.getInstance();
//2.通過委托對象調(diào)用方法
WebResourceResponse webResourceResponse = webViewCacheDelegate.interceptRequest(url);
- 關(guān)于shouldOverrideUrlLoading處理多類型
- 比如:封裝庫中需要處理打電話,發(fā)短信,發(fā)郵件,地圖定位,圖片,超鏈接等攔截邏輯
- 最剛開始是把處理的邏輯都放到了WebViewClient中的shouldOverrideUrlLoading方法中處理。不過發(fā)現(xiàn)這個類代碼越來越多……
- 后期演變,針對電話短信等將處理邏輯抽取到WebSchemeIntent類中,針對圖片處理邏輯抽取到SaveImageProcessor類中。具體看WebSchemeIntent
- 這樣做,相當于保證了類的單一性職責,即類盡量保證內(nèi)部處理的功能盡可能單一,而不是錯綜復雜……
08.關(guān)于后期需要研究的目標
- 目標
- web頁面特別消耗流量,每次打開頁面都會請求網(wǎng)絡(luò),建議對流量的消耗進行優(yōu)化……除了對lib庫中對攔截做OkHttp緩存,還有什么其他方案
- web頁面涉及流量的幾個方面
- 普通https請求,一般過程是服務(wù)端(對象)-->網(wǎng)絡(luò)中(二進制流)-->客戶端(對象),文本內(nèi)容會做傳輸壓縮
- 網(wǎng)絡(luò)圖片下載,圖片下載消耗的流量較多
- h5頁面展示,由于h5頁面是交由前端處理顯示,客戶端開發(fā)關(guān)注的少些,而此處消耗了大量的流量
- 如何查看web頁面消耗流量
- 使用TrafficStats即可查看流量的消耗
09.開源庫
- 1.最剛開始把視頻全屏show和hide的邏輯都放到X5WebChromeClient中處理,相當于這個類中邏輯比較多
- 2.后期把視頻全屏播放邏輯都抽到了VideoWebChromeClient類中處理,這樣只需要繼承該類即可。這個類獨立,拿來即用。
- 3.后期演變,一個視頻全屏播放接口 + 接口實現(xiàn)類 + VideoChromeClient,接口主要能夠解耦
- 1.代碼結(jié)構(gòu)大概是:攔截緩存接口 + 接口實現(xiàn)類 + 接口委派類
- 2.優(yōu)點:委派類和實現(xiàn)類解耦;便于增加過濾功能(比如用了https+dns優(yōu)化就不用攔截緩存);
//1.創(chuàng)建委托對象
WebViewCacheDelegate webViewCacheDelegate = WebViewCacheDelegate.getInstance();
//2.通過委托對象調(diào)用方法
WebResourceResponse webResourceResponse = webViewCacheDelegate.interceptRequest(url);
- 比如:封裝庫中需要處理打電話,發(fā)短信,發(fā)郵件,地圖定位,圖片,超鏈接等攔截邏輯
- 最剛開始是把處理的邏輯都放到了WebViewClient中的shouldOverrideUrlLoading方法中處理。不過發(fā)現(xiàn)這個類代碼越來越多……
- 后期演變,針對電話短信等將處理邏輯抽取到WebSchemeIntent類中,針對圖片處理邏輯抽取到SaveImageProcessor類中。具體看WebSchemeIntent
- 這樣做,相當于保證了類的單一性職責,即類盡量保證內(nèi)部處理的功能盡可能單一,而不是錯綜復雜……
- web頁面特別消耗流量,每次打開頁面都會請求網(wǎng)絡(luò),建議對流量的消耗進行優(yōu)化……除了對lib庫中對攔截做OkHttp緩存,還有什么其他方案
- 普通https請求,一般過程是服務(wù)端(對象)-->網(wǎng)絡(luò)中(二進制流)-->客戶端(對象),文本內(nèi)容會做傳輸壓縮
- 網(wǎng)絡(luò)圖片下載,圖片下載消耗的流量較多
- h5頁面展示,由于h5頁面是交由前端處理顯示,客戶端開發(fā)關(guān)注的少些,而此處消耗了大量的流量
- 使用TrafficStats即可查看流量的消耗