前言
權(quán)當(dāng)給自己的記錄,而且WebView 坑很多
目錄
- 一:生命周期
- 二:WebView 主要的3個類
- WebSettings
- WebViewClient
- WebChromeClient
- 三: WebView緩存實現(xiàn)
- 四: Cookies
- 五: 關(guān)于前進 / 后退網(wǎng)頁
- 六:常見問題
- 參考
添加網(wǎng)絡(luò)權(quán)限
<uses-permission android:name="android.permission.INTERNET" />
一:生命周期
onResume()
WebView為活躍狀態(tài)時回調(diào),可以正常執(zhí)行網(wǎng)頁的響應(yīng)。
onPause()
WebView被切換到后臺時回調(diào), 頁面被失去焦點, 變成不可見狀態(tài)柒巫,onPause動作通知內(nèi)核暫停所有的動作,比如DOM的解析、plugin的執(zhí)行卦尊、JavaScript執(zhí)行。
pauseTimers()
當(dāng)應(yīng)用程序被切換到后臺時回調(diào)舌厨,該方法針對全應(yīng)用程序的WebView岂却,它會暫停所有webview的layout,parsing,javascripttimer躏哩。降低CPU功耗署浩。
resumeTimers()
恢復(fù)pauseTimers時的動作。
destroy()
關(guān)閉了Activity時回調(diào), WebView調(diào)用destory時, WebView仍綁定在Activity上.這是由于自定義WebView構(gòu)建時傳入了該Activity的context對象, 因此需要先從父
容器中移除WebView, 然后再銷毀webview扫尺。
mRootLayout.removeView(webView);
mWebView.destroy();
二:WebView 主要的3個類
1. WebSettings
WebSettings用來對WebView做各種設(shè)置, 你可以這樣獲取WebSettings
WebSettings webSettings = mWebView .getSettings();
JS處理
setJavaScriptEnabled(true); //支持js
setPluginsEnabled(true); //支持插件
setJavaScriptCanOpenWindowsAutomatically(true); //支持通過JS打開新窗口
縮放處理
setUseWideViewPort(true); //將圖片調(diào)整到適合webview的大小
setLoadWithOverviewMode(true); // 縮放至屏幕的大小
setSupportZoom(true); //支持縮放筋栋,默認(rèn)為true。是下面那個的前提正驻。
setBuiltInZoomControls(true); //設(shè)置內(nèi)置的縮放控件弊攘。 這個取決于setSupportZoom(), 若setSupportZoom(false),則該WebView不可縮放姑曙,這個不管設(shè)置什么都不能縮放襟交。
setDisplayZoomControls(false); //隱藏原生的縮放控件
內(nèi)容布局
setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); //支持內(nèi)容重新布局
supportMultipleWindows(); //多窗口
文件緩存
setAllowFileAccess(true); //設(shè)置可以訪問文件
setDomStorageEnabled(true); // 開啟 DOM storage API 功能
setDatabaseEnabled(true); //開啟 database storage API 功能
setAppCacheEnabled(true);//開啟 Application Caches 功能
String cacheDirPath = getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME;
webSettings.setAppCachePath(cacheDirPath); //設(shè)置 Application Caches 緩存目錄
每個 Application 只調(diào)用一次 WebSettings.setAppCachePath(),WebSettings.setAppCacheMaxSize()
其他設(shè)置
setNeedInitialFocus(true); //當(dāng)webview調(diào)用requestFocus時為webview設(shè)置節(jié)點
setLoadsImagesAutomatically(true); //支持自動加載圖片
setDefaultTextEncodingName(“utf-8”); //設(shè)置編碼格式
setPluginState(PluginState.OFF); //設(shè)置是否支持flash插件
setDefaultFontSize(20); //設(shè)置默認(rèn)字體大小
2. WebViewClient
WebViewClient用來幫助WebView處理各種通知, 請求事件伤靠。我們通過繼承WebViewClient并重載它的方法可以實現(xiàn)不同功能的定制
(1)shouldOverrideUrlLoading()
作用:打開網(wǎng)頁時不調(diào)用系統(tǒng)瀏覽器捣域, 而是在本W(wǎng)ebView中顯示;在網(wǎng)頁上的所有加載都經(jīng)過這個方法,這個函數(shù)我們可以做很多操作醋界。
//步驟1. 定義Webview組件
Webview webview = (WebView) findViewById(R.id.webView1);
//步驟2. 選擇加載方式
//方式1. 加載一個網(wǎng)頁:
webView.loadUrl("http://www.google.com/");
//方式2:加載apk包中的html頁面
webView.loadUrl("file:///android_asset/test.html");
//方式3:加載手機本地的html頁面
webView.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");
//步驟3. 復(fù)寫shouldOverrideUrlLoading()方法竟宋,使得打開網(wǎng)頁時不調(diào)用系統(tǒng)瀏覽器, 而是在本W(wǎng)ebView中顯示
webView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
(2)onPageStarted()
作用:開始載入頁面調(diào)用的形纺,我們可以設(shè)定一個loading的頁面丘侠,告訴用戶程序在等待網(wǎng)絡(luò)響應(yīng)。
webView.setWebViewClient(new WebViewClient(){
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
//設(shè)定加載開始的操作
}
});
(3) onPageFinished()
作用:在頁面加載結(jié)束時調(diào)用逐样。我們可以關(guān)閉loading 條蜗字,切換程序動作。
webView.setWebViewClient(new WebViewClient(){
@Override
public void onPageFinished(WebView view, String url) {
//設(shè)定加載結(jié)束的操作
}
});
(4)onLoadResource()
作用:在加載頁面資源時會調(diào)用脂新,每一個資源(比如圖片)的加載都會調(diào)用一次挪捕。
webView.setWebViewClient(new WebViewClient(){
@Override
public boolean onLoadResource(WebView view, String url) {
//設(shè)定加載資源的操作
}
});
(5)onReceivedError()
作用:加載頁面的服務(wù)器出現(xiàn)錯誤時(如404)調(diào)用。
App里面使用webview控件的時候遇到了諸如404這類的錯誤的時候争便,若也顯示瀏覽器里面的那種錯誤提示頁面就顯得很丑陋了级零,那么這個時候我們的app就需要加載一個本地的錯誤提示頁面,即webview如何加載一個本地的頁面
//步驟1:寫一個html文件(error_handle.html)滞乙,用于出錯時展示給用戶看的提示頁面
//步驟2:將該html文件放置到代碼根目錄的assets文件夾下
//步驟3:復(fù)寫WebViewClient的onRecievedError方法
//該方法傳回了錯誤碼奏纪,根據(jù)錯誤類型可以進行不同的錯誤分類處理
webView.setWebViewClient(new WebViewClient(){
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl){
switch(errorCode)
{
case HttpStatus.SC_NOT_FOUND:
view.loadUrl("file:///android_assets/error_handle.html");
break;
}
}
});
(6) onReceivedSslError()
作用:處理https請求
webView默認(rèn)是不處理https請求的,頁面顯示空白斩启,需要進行如下設(shè)置:
webView.setWebViewClient(new WebViewClient() {
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed(); //表示等待證書響應(yīng)
// handler.cancel(); //表示掛起連接序调,為默認(rèn)方式
// handler.handleMessage(null); //可做其他處理
}
});
3. WebChromeClient
輔助 WebView 處理 Javascript 的對話框,網(wǎng)站圖標(biāo),網(wǎng)站標(biāo)題等等。
(1) onProgressChanged()
:獲得網(wǎng)頁的加載進度并顯示
webview.setWebChromeClient(new WebChromeClient(){
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (newProgress < 100) {
String progress = newProgress + "%";
progress.setText(progress);
} else {
}
});
(2) onReceivedTitle()
獲取Web頁中的標(biāo)題
每個網(wǎng)頁的頁面都有一個標(biāo)題兔簇,比如www.baidu.com這個頁面的標(biāo)題即“百度一下发绢,你就知道”硬耍,那么如何知道當(dāng)前webview正在加載的頁面的title并進行設(shè)置呢?
webview.setWebChromeClient(new WebChromeClient(){
@Override
public void onReceivedTitle(WebView view, String title) {
titleview.setText(title)边酒;
}
三: WebView緩存實現(xiàn)
在項目中如果使用到WebView控件, 當(dāng)加載html頁面時, 會在/data/data/包名目錄下生成database與cache兩個文件夾经柴。
請求的url記錄是保存在WebViewCache.db, 而url的內(nèi)容是保存在WebViewCache文件夾下。
控制緩存行為
WebSettings webSettings = mWebView.getSettings();
//優(yōu)先使用緩存
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
//(默認(rèn))根據(jù)cache-control決定是否從網(wǎng)絡(luò)上取數(shù)據(jù)
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
//只在緩存中讀取
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ONLY);
//不使用緩存
WwebSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
清除緩存
//清除網(wǎng)頁訪問留下的緩存墩朦,由于內(nèi)核緩存是全局的因此這個方法不僅僅針對webview而是針對整個應(yīng)用程序.
clearCache(true);
//清除當(dāng)前webview訪問的歷史記錄口锭,只會webview訪問歷史記錄里的所有記錄除了當(dāng)前訪問記錄.
clearHistory ();
//這個api僅僅清除自動完成填充的表單數(shù)據(jù),并不會清除WebView存儲到本地的數(shù)據(jù)介杆。
clearFormData ()
四: Cookies
添加Cookies
public void synCookies() {
if (!CacheUtils.isLogin(this)) return;
CookieSyncManager.createInstance(this);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.removeSessionCookie();//移除
String cookies = PreferenceHelper.readString(this, AppConfig.COOKIE_KEY, AppConfig.COOKIE_KEY);
KJLoger.debug(cookies);
cookieManager.setCookie(url, cookies);
CookieSyncManager.getInstance().sync();
}
清除Cookies
CookieManager.getInstance().removeSessionCookie();
五: 關(guān)于前進 / 后退網(wǎng)頁
WebView的狀態(tài)
//激活WebView為活躍狀態(tài)鹃操,能正常執(zhí)行網(wǎng)頁的響應(yīng)
webView.onResume() ;
//當(dāng)頁面被失去焦點被切換到后臺不可見狀態(tài)春哨,需要執(zhí)行onPause
//通過onPause動作通知內(nèi)核暫停所有的動作荆隘,比如DOM的解析、plugin的執(zhí)行赴背、JavaScript執(zhí)行椰拒。
webView.onPause();
//當(dāng)應(yīng)用程序(存在webview)被切換到后臺時凰荚,這個方法不僅僅針對當(dāng)前的webview而是全局的全應(yīng)用程序的webview
//它會暫停所有webview的layout燃观,parsing,javascripttimer便瑟。降低CPU功耗缆毁。
webView.pauseTimers()
//恢復(fù)pauseTimers狀態(tài)
webView.resumeTimers();
//銷毀Webview
//在關(guān)閉了Activity時到涂,如果Webview的音樂或視頻脊框,還在播放。就必須銷毀Webview
//但是注意:webview調(diào)用destory時,webview仍綁定在Activity上
//這是由于自定義webview構(gòu)建時傳入了該Activity的context對象
//因此需要先從父容器中移除webview,然后再銷毀webview:
rootLayout.removeView(webView);
webView.destroy();
//是否可以后退
Webview.canGoBack()
//后退網(wǎng)頁
Webview.goBack()
//是否可以前進
Webview.canGoForward()
//前進網(wǎng)頁
Webview.goForward()
//以當(dāng)前的index為起始點前進或者后退到歷史記錄中指定的steps
//如果steps為負數(shù)則為后退践啄,正數(shù)則為前進
Webview.goBackOrForward(intsteps)
常見用法:Back鍵控制網(wǎng)頁后退
- 問題:在不做任何處理前提下 浇雹,瀏覽網(wǎng)頁時點擊系統(tǒng)的“Back”鍵,整個 Browser 會調(diào)用 finish()而結(jié)束自身
- 目標(biāo):點擊返回后,是網(wǎng)頁回退而不是推出瀏覽器
- 解決方案:在當(dāng)前Activity中處理并消費掉該 Back 事件
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
六:常見問題
1. android webview ZoomButtonsController導(dǎo)致android.view.WindowLeaked 問題徹底解決
@Override
public void finish() {
ViewGroup view = (ViewGroup) getWindow().getDecorView();
view.removeAllViews();
super.finish();
}