Android Webview的postUrl與loadUrl加載頁(yè)面實(shí)例
關(guān)于Android的webview,用過(guò)的想必都不會(huì)陌生。這里我就不說(shuō)webview的基本用法了,想要知道的可以去網(wǎng)上百多,有很多介紹webview基本用法的。
本文要介紹的主要是在項(xiàng)目過(guò)程中使用webview的postUrl遇到的坑。
1、使用場(chǎng)景如下:
webview在加載H5鏈接時(shí),默認(rèn)是使用loadUrl進(jìn)行加載,如果你設(shè)置了緩存屬性(進(jìn)行緩存),在顯示的H5頁(yè)面內(nèi)點(diǎn)擊跳轉(zhuǎn)到另外一個(gè)頁(yè)面后,按回退鍵,可以正常的返回到上一個(gè)頁(yè)面,因?yàn)檫M(jìn)行了緩存設(shè)置。但是如果使用postUrl進(jìn)行加載,即使你設(shè)置的緩存屬性是進(jìn)行設(shè)置,當(dāng)你調(diào)轉(zhuǎn)到另外一個(gè)頁(yè)面后,按回退鍵,不會(huì)緩存之前的頁(yè)面,而是重新調(diào)用postUrl進(jìn)行加載。這時(shí)問(wèn)題就來(lái)了,同樣是進(jìn)行加載,第一次的postUrl能夠正常加載,重新加載會(huì)加載失敗,沒(méi)有內(nèi)容顯示。是不是很有意思,為什么會(huì)出現(xiàn)這樣的情況呢,通過(guò)抓包發(fā)現(xiàn),雖然加載的是同樣一個(gè)鏈接,但是重新加載的請(qǐng)求屬性為空,導(dǎo)致加載失敗。
2、如何解決:
既然找到了原因,請(qǐng)求屬性為空,肯定是有解決辦法的,那就手動(dòng)設(shè)置請(qǐng)求屬性,重新加載。如何手動(dòng)設(shè)置,首先你肯定是要能夠拿到請(qǐng)求的所有內(nèi)容和參數(shù)。用過(guò)webview的人相必都很熟悉它的setWebViewClient方法。該方法內(nèi)部有shouldInterceptRequest方法能夠拿到請(qǐng)求的所有內(nèi)容。不多說(shuō)了,先上代碼。
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
if(Build.VERSION.SDK_INT >= 21){
if(!request.getMethod().equalsIgnoreCase("post")){
return super.shouldInterceptRequest(view, request);
}
}
DataOutputStream os = null;
try {
URL mUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) mUrl.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
if(Build.VERSION.SDK_INT >= 21){
Iterator headerKeys=request.getRequestHeaders().keySet().iterator();
while(headerKeys.hasNext()){
String key=headerKeys.next();
connection.setRequestProperty(key,request.getRequestHeaders().get(key));
}
}
connection.setRequestProperty("content-type","application/x-www-form-urlencoded");
os = new DataOutputStream(connection.getOutputStream());
os.write(EncodingUtils.getBytes(postData, "BASE64"));
os.flush();
return new WebResourceResponse("text/html", connection.getContentEncoding(), connection.getInputStream());
} catch (Exception e) {
e.printStackTrace();
}finally {
if(os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return super.shouldInterceptRequest(view, request);
}
});
webView.postUrl(url, EncodingUtils.getBytes(postData, "BASE64"));
該方法有個(gè)缺陷,只在Android 5.0.0以上的Api才有,5.0.0以下的Api是沒(méi)有此方法的,這也是一個(gè)坑,不能兼容所有機(jī)型。通過(guò)該方法中的setRequestProperty方法重新設(shè)置了請(qǐng)求屬性,然后使用postUrl進(jìn)行重新加載,可以解決按回退鍵后頁(yè)面的重新恢復(fù)。注意,由于post加載是不能緩存的,因此在設(shè)置緩存屬性時(shí)一定要設(shè)置成重新加載屬性。
3、解決后出現(xiàn)的問(wèn)題:
問(wèn)題看似解決了,但是此方法會(huì)有坑。如果你仔細(xì)研究該方法,你會(huì)發(fā)現(xiàn)shouldInterceptRequest方法是在整個(gè)加載過(guò)中都調(diào)用了的。如果你進(jìn)行抓包,你會(huì)發(fā)現(xiàn),從開(kāi)始加載鏈接到H5頁(yè)面中加載的每一個(gè)請(qǐng)求,該方法都會(huì)被調(diào)用,簡(jiǎn)單的說(shuō)就是有多少個(gè)請(qǐng)求,該方法就會(huì)調(diào)用多少次。如果你的頁(yè)面中還有一次post請(qǐng)求,那么問(wèn)題就來(lái)了,你需要將第二次post請(qǐng)求的請(qǐng)求內(nèi)容與第一次的進(jìn)行對(duì)比,對(duì)比后選擇到底是加載第一次的頁(yè)面,還是加載第二次的頁(yè)面,否則就會(huì)默認(rèn)加載第一次的post頁(yè)面。
4、結(jié)論
webview的H5頁(yè)面加載最好使用loadUrl方式,如果使用postUrl方式進(jìn)行加載,你需要重寫(xiě)整個(gè)setWebViewClient方法,當(dāng)中會(huì)出很多坑,不建議這樣做。
以上這篇Android Webview的postUrl與loadUrl加載頁(yè)面實(shí)例就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- 深入解析Android中的setContentView加載布局原理
- 淺析Android Dialog中setContentView()方法
- Android開(kāi)發(fā)中setContentView和inflate的區(qū)別分析
- Android開(kāi)發(fā)微信小程序頁(yè)面的圖文教程
- Android 登錄頁(yè)面的實(shí)現(xiàn)代碼(密碼顯示隱藏、EditText 圖標(biāo)切換、限制輸入長(zhǎng)度)
- Android Studio使用recyclerview實(shí)現(xiàn)展開(kāi)和折疊功能(在之前的微信頁(yè)面基礎(chǔ)之上)
- Android通過(guò)ViewModel保存數(shù)據(jù)實(shí)現(xiàn)多頁(yè)面的數(shù)據(jù)共享功能
- Android仿微信左右滑動(dòng)點(diǎn)擊切換頁(yè)面和圖標(biāo)
- Android仿淘寶訂單頁(yè)面效果
- Android使用setContentView實(shí)現(xiàn)頁(yè)面的轉(zhuǎn)換效果
相關(guān)文章
Flutter之自定義Dialog實(shí)現(xiàn)版本更新彈窗功能的實(shí)現(xiàn)
這篇文章主要介紹了Flutter之自定義Dialog實(shí)現(xiàn)版本更新彈窗功能的實(shí)現(xiàn),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
android實(shí)現(xiàn)listview分頁(yè)的方法
這篇文章主要介紹了android實(shí)現(xiàn)listview分頁(yè)的方法,涉及Android生成listview列表的相關(guān)技巧,需要的朋友可以參考下2015-05-05
android圖像繪制(四)自定義一個(gè)SurfaceView控件
自定義控件(類似按鈕等)的使用,自定義一個(gè)SurfaceView。如某一塊的動(dòng)態(tài)圖(自定義相應(yīng)),或者類似UC瀏覽器下面的工具欄,感興趣的朋友可以了解下2013-01-01
Android Studio 3.6 正式版終于發(fā)布了,快來(lái)圍觀
Android Studio 3.6 正式版終于發(fā)布了,值得興奮呀,畢竟 3.5 大版本更新也已經(jīng)差不多半年了,撒花撒花!這次更新又更新了什么呢?快來(lái)跟隨小編一起看看吧2020-02-02
深入解析Android App的LayoutInflate布局
這篇文章主要介紹了Android App的LayoutInflate布局,對(duì)LayoutInflate編寫(xiě)中經(jīng)常被無(wú)解及產(chǎn)生錯(cuò)誤的地方進(jìn)行了深入說(shuō)明,需要的朋友可以參考下2016-04-04
Android實(shí)現(xiàn)朋友圈評(píng)論回復(fù)列表
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)朋友圈評(píng)論回復(fù)列表,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11
Android編程設(shè)計(jì)模式之解釋器模式詳解
這篇文章主要介紹了Android編程設(shè)計(jì)模式之解釋器模式,詳細(xì)分析了Android解釋器模式的概念、原理、使用場(chǎng)景、使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2017-12-12
Android自定義View onDraw()方法會(huì)調(diào)用兩次的問(wèn)題解決
這篇文章主要介紹了Android自定義View onDraw()方法會(huì)調(diào)用兩次的問(wèn)題解決,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-01-01
Android基于API的Tabs3實(shí)現(xiàn)仿優(yōu)酷t(yī)abhost效果實(shí)例
這篇文章主要介紹了Android基于API的Tabs3實(shí)現(xiàn)仿優(yōu)酷t(yī)abhost效果,結(jié)合完整實(shí)例形式分析了Android實(shí)現(xiàn)優(yōu)酷界面效果的相關(guān)技巧,需要的朋友可以參考下2015-12-12

