Android - WebView詳解

老婆保佑,代碼無BUG

前言

權(quán)當(dāng)給自己的記錄,而且WebView 坑很多


目錄

  • 一:生命周期
  • 二:WebView 主要的3個類
      1. WebSettings
      1. WebViewClient
      1. 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();

    }

參考

WebView基本用法(郭嘉 )

Android:最全面的 Webview 詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末屿讽,一起剝皮案震驚了整個濱河市昭灵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌伐谈,老刑警劉巖烂完,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異衩婚,居然都是意外死亡窜护,警方通過查閱死者的電腦和手機效斑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門非春,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事奇昙』の辏” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵储耐,是天一觀的道長羊初。 經(jīng)常有香客問我,道長什湘,這世上最難降的妖魔是什么长赞? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮闽撤,結(jié)果婚禮上得哆,老公的妹妹穿的比我還像新娘。我一直安慰自己哟旗,他們只是感情好贩据,可當(dāng)我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著闸餐,像睡著了一般饱亮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上舍沙,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天近上,我揣著相機與錄音,去河邊找鬼拂铡。 笑死戈锻,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的和媳。 我是一名探鬼主播格遭,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼留瞳!你這毒婦竟也來了拒迅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤她倘,失蹤者是張志新(化名)和其女友劉穎璧微,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體硬梁,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡前硫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了荧止。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屹电。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡阶剑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出危号,到底是詐尸還是另有隱情牧愁,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布外莲,位于F島的核電站猪半,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏偷线。R本人自食惡果不足惜磨确,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望声邦。 院中可真熱鬧俐填,春花似錦、人聲如沸翔忽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽歇式。三九已至驶悟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間材失,已是汗流浹背痕鳍。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留龙巨,地道東北人笼呆。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像旨别,于是被迫代替她去往敵國和親诗赌。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容