Android學習之 WebView使用小結

    這段時間基於項目需要 在開發中與WebView的接觸比較多,前段時間關於HTML5規範塵埃落定的消息出現在各大IT社區頭版上,更有人說:HTML5將顛覆原生App開發 儘管我不太認同這一點 但是關於HTML5+JS+CSS+Native的跨平臺開發模式仍是爲很是多企業節省了開發資源和成本、必定程度上提高了WebView的使用率和地位。


網上關於HTML5規範定稿的一篇看法文章:javascript

http://www.csdn.net/article/2014-11-06/2822513-how-html5-changescss


本篇主要基於這段時間對WebView的使用經驗和網上學習到的對WebView開發作一個要點小結:html


1、WebView基於webkit引擎展示web頁面的控件,使用前需要在Android Manifest file中配置internet訪問權限,不然提示頁面沒法訪問。html5

<manifest ... >
    <uses-permission android:name="android.permission.INTERNET" />
    ...
</manifest>


2、WebView屬性的設置
  一、設置WebSettings類
     WebSettings用來對WebView的配置進行配置和管理,比方可否夠進行文件操做、緩存的設置、頁面是否支持放大和縮小、是否贊成使用數據庫api、字體及文字編碼設置、是否贊成js腳本執行、是否贊成圖片本身主動載入、是否贊成數據及password保存等等
     演示樣例代碼例如如下:

WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); 
webSettings.setDomStorageEnabled(true);  
webSettings.setDatabaseEnabled(true);
webSettings.setAppCacheEnabled(true); 
webSettings.setAllowFileAccess(true);
webSettings.setSavePassword(true);
webSettings.setSupportZoom(true);
webSettings.setBuiltInZoomControls(true); 
 /**
  * 用WebView顯示圖片,可以使用這個參數 設置網頁佈局類型:
  * 一、LayoutAlgorithm.NARROW_COLUMNS :適應內容大小
  * 二、LayoutAlgorithm.SINGLE_COLUMN : 適應屏幕,內容將本身主動縮放
  */
webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
webSettings.setUseWideViewPort(true); 

mWebView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
mWebView.setHorizontalScrollbarOverlay(true);
mWebView.setHorizontalScrollBarEnabled(true);
mWebView.requestFocus(); 
  二、設置WebChromeClient子類
      WebChromeClient會在一些影響瀏覽器ui交互動做發生時被調用,比方WebView關閉和隱藏、頁面載入進展、js確認框和警告框、js載入前、js操做超時、webView得到焦點等等

mWebView.setWebChromeClient(new MyWebChromeClient());
三、設置WebViewClient子類
     WebViewClient會在一些影響內容渲染的動做發生時被調用,比方表單的錯誤提交需要又一次提交、頁面開始載入及載入完畢、資源載入中、接收到https認證需要處理、頁面鍵盤響應、頁面中的url打開處理等等

mWebView.setWebViewClient(new MyWebViewClient());
四、設置addJavascriptInterface方法
     使Js調用Native本地Java對象,實現本地Java代碼和HTML頁面進行交互,
     注意:因爲安全問題的考慮 Google在使用Android API 17以上的版本號的時候 需要經過@JavascriptInterface來註解的Java函數才幹被識別可以被Js調用。


3、設置當前網頁的連接仍在WebView中跳轉,而不是跳到手機瀏覽器裏顯示,
       在WebViewClient的子類中重寫shouldOverrideUrlLoading函數  代碼例如如下:
java

webView.setWebViewClient(new WebViewClient() {  
  
    @Override  
    public boolean shouldOverrideUrlLoading(WebView view, String url) {  
        view.loadUrl(url);  
        return true;  
    }  
}); 
shouldOverrideUrlLoading表示當前webView中的一個新url需要載入時,給當前應用程序一個處理機會,假設沒有重寫此函數,webView請求ActivityManage選擇合適的方式處理請求,就像彈出uc和互聯網讓用戶選擇瀏覽器同樣。重寫後return true表示讓當前程序處理,return false表示讓當前webView處理

4、設置開始載入網頁、載入完畢、載入錯誤時處理
   在WebViewClient子類中分別重寫例如如下父類函數  代碼例如如下:

webView.setWebViewClient(new WebViewClient() {  
  
    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        super.onPageStarted(view, url, favicon);
        // 開始載入網頁時處理 如:顯示"載入提示" 的載入對話框
        DialogManager.showLoadingDialog(this);
    }

    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        // 網頁載入完畢時處理  如:讓 載入對話框 消失
        DialogManager.dismissLoadingDialog();
    }

    @Override
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
        super.onReceivedError(view, errorCode, description, failingUrl);
        // 載入網頁失敗時處理  如:
        view.loadDataWithBaseURL(null,
                "<span style=\"color:#FF0000\">網頁載入失敗</span>",
                "text/html",
                "utf-8",
                null);
    }  
});
5、處理https請求,爲WebView處理ssl證書設置
    WebView默認是不處理https請求的,頁面顯示空白,需要進行例如如下設置
    在WebViewClient子類中重寫父類的onReceivedSslError函數  代碼例如如下:

webView.setWebViewClient(new WebViewClient() {  
  
    @Override
    public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
        handler.proceed();  // 接受信任所有站點的證書
        // handler.cancel();   // 默認操做 不處理
        // handler.handleMessage(null);  // 可作其它處理
    } 
}); 

6、顯示頁面載入進度
   在WebChromeClient子類中重寫父類的onProgressChanged函數  代碼例如如下:

webView.setWebChromeClient(new WebChromeClient() {  
  
    public void onProgressChanged(WebView view, int progress) {  
        setTitle("頁面載入中,請稍候..." + progress + "%");  
        setProgress(progress * 100);  
  
        if (progress == 100) {  
            setTitle(R.string.app_name);  
        }  
    }  
});
onProgressChanged通知應用程序當前頁面載入的進度
progress表示當前頁面載入的進度,爲1至100的整數

7、back鍵控制網頁後退
   Activity默認的back鍵處理爲結束當前Activity,WebView查看了很是多網頁後,但願按back鍵返回上一次瀏覽的頁面,這個時候咱們就需要覆蓋WebView所在Activity的onKeyDown函數,告訴他怎樣處理,代碼例如如下:

public boolean onKeyDown(int keyCode, KeyEvent event) {  
    if (webView.canGoBack() && event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {  
        webView.goBack();  
        return true;  
    }  
    return super.onKeyDown(keyCode, event);  
}
當中webView.canGoBack()在webView含有一個可後退的瀏覽記錄時返回true
webView.goBack();表示返回至webView的上次訪問頁面


8、使用addJavascriptInterface完畢和js交互
一、Js中調Native本地Java方法
  設置webView的addJavascriptInterface方法,該方法有兩個參數,第一個參數爲被綁定到js中的類實例,第二個參數爲在js中暴露的類別名,在js中引用java對象就是用這個名字
在Native Java代碼例如如下:
android

mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JavaScriptInterface(this), "Android");

class JavaScriptInterface{

    Context mContext;

    /** Instantiate the interface and set the context */
    JavaScriptInterface(Context c) {
        mContext = c;
    }

    /** Show a toast from the web page 
      * 由Js調用運行Native本地Java方法
      */
    @JavascriptInterface
    public void showToast(String toast) {
        Log.d("TAG", "Js Invoker Native Function");
        Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
    }		
		
}
在HTML中Js調用Native方法 代碼例如如下:

<input type="button" value="Say hello" onClick="showAndroidToast('Hello Android!')" />

<script type="text/javascript">
    function showAndroidToast(toast) {
        Android.showToast(toast);
    }
</script>
二、Java調Js方法
比方在HTML中有例如如下Js函數

<script type="text/javascript">
      function showAlert() {
        alert("Be executed by Native");
    }
</script>
在Native調Js方法例如如下:

mWebView.loadUrl("javascript:showAlert()");

9、WebView緩存模式的設置
一、網頁數據緩存
當使用WebView載入HTML網頁時,會在咱們data/應用package下生成database與cache兩個目錄:
咱們請求的Url記錄是保存在webviewCache.db裏,而url的內容是保存在webviewCache目錄下.

五種緩存模式的設置setCacheMode:
LOAD_CACHE_ONLY:  不使用網絡,僅僅讀取本地緩存數據。
LOAD_DEFAULT:  依據cache-control決定是否從網絡上取數據。
LOAD_CACHE_NORMAL: API level 17中已經廢棄, 從API level 11開始做用同LOAD_DEFAULT模式。
LOAD_NO_CACHE: 不使用緩存,僅僅從網絡獲取數據。
LOAD_CACHE_ELSE_NETWORK,僅僅要本地有,不論是否過時,或者no-cache,都使用緩存中的數據。

如演示樣例代碼:

WebSettings webSettings = mWebView.getSettings();
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);  //設置 緩存模式  
// 開啓 DOM storage API 功能  
webSettings.setDomStorageEnabled(true);  
//開啓 database storage API 功能  
webSettings.setDatabaseEnabled(true);  

二、H5緩存
經過setAppCacheEnabled(boolean flag)設置H5的緩存是否打開,默認關閉。
依據setAppCachePath(String appCachePath)提供的路徑,在H5使用緩存過程當中生成的緩存文件。
經過setAppCacheMaxSize(long appCacheMaxSize)設置緩存最大容量。

如演示樣例代碼:

String cacheDirPath = getCacheDir().getAbsolutePath()+ "/webViewCache ";
WebSettings webSettings = mWebView.getSettings();
//開啓 database storage API 功能  
webSettings.setDatabaseEnabled(true);    
//設置數據庫緩存路徑  
webSettings.setDatabasePath(cacheDirPath); 
//開啓Application H5 Caches 功能  
webSettings.setAppCacheEnabled(true); 
//設置Application Caches 緩存文件夾  
webSettings.setAppCachePath(cacheDirPath);

10、加快HTML網頁載入完畢速度
    默認狀況html代碼下載到WebView後,webkit開始解析網頁各個節點,發現有外部樣式文件或者外部腳本文件時,會異步發起網絡請求下載文件,但假設在這以前也有解析到image節點,那勢必也會發起網絡請求下載對應的圖片。在網絡狀況較差的狀況下,過多的網絡請求就會形成帶寬緊張,影響到css或js文件載入完畢的時間,形成頁面空白loading太久。解決辦法就是告訴WebView先不要本身主動載入圖片,等頁面finish後再發起圖片載入。
    故在WebView初始化時設置例如如下代碼:

public void int () {
    if(Build.VERSION.SDK_INT >= 19) {
        webView.getSettings().setLoadsImagesAutomatically(true);
    } else {
        webView.getSettings().setLoadsImagesAutomatically(false);
    }
}
同一時候在WebView的WebViewClient子類中重寫onPageFinished()方法加入例如如下代碼:

@Override
public void onPageFinished(WebView view, String url) {
    if(!webView.getSettings().getLoadsImagesAutomatically()) {
        webView.getSettings().setLoadsImagesAutomatically(true);
    }
}
從上面的代碼,可以看出咱們對系統API在19以上的版本號做了兼容。因爲4.4以上系統在onPageFinished時再恢復圖片載入時,假設存在多張圖片引用的是一樣的src時,會僅僅有一個image標籤獲得載入,於是對於這種系統咱們就先直接載入。


11、WebView硬件加速致使頁面渲染閃爍問題解決方法
    關於Android硬件加速 開始於Android 3.0 (API level 11),在四個級別上開啓/關閉硬件加速
    一、Application級別:爲整個應用程序開啓硬件加速,在AndroidManifest中增長例如如下配置
web

<application android:hardwareAccelerated="true" ...>
      二、Activity級別:控制每個activity是否開啓硬件加速,僅僅需在activity元素中加入android:hardwareAccelerated屬性就能夠

<activity android:hardwareAccelerated="true" ...>
   三、Window級別:注:眼下還不支持在Window級別上關閉硬件加速

getWindow().setFlags(
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
   四、View級別:執行時單個view硬件加速,眼下Android還不支持在View級別開啓硬件加速  代碼例如如下:

mView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    

 [//TODO 關於Android硬件加速 小呂有時間會更具體的單獨整理成一篇來作介紹 
     先提供學習地址:http://android.toolib.net/guide/topics/graphics/hardware-accel.html]

     咱們開啓硬件加速後,WebView渲染頁面更加高速,拖動也更加順滑。但有個反作用就是easy會出現頁面載入白塊同一時候界面閃爍現象。解決問題的方法是設置WebView臨時關閉硬件加速 代碼例如如下:
數據庫

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}


12、WebView載入本地HTML文件亂碼問題解決方式
分析1、保證html頁面有設置編碼格式 
如:       api

<meta http-equiv="content-type" content="text/html;charset=utf-8"/>

分析2、爲WebView 指定顯示的編碼,WebView設置編碼是在Settings中來設置,如:         瀏覽器

mWebView.getSettings().setDefaultTextEncodingName("utf-8");
分析3、假設你是使用的loadData()來載入顯示網頁。中文出現亂碼 則改成loadDataWithBaseURL
             緣由:webview.loadData方法不支持中文解析,通常用webView.loadDataWithBaseURL來解決。如:          
//webview.loadData(data, "text/html", "utf-8");
  webview.loadDataWithBaseURL(baseUrl, data, "text/html", "utf-8", failUrl);


十3、其它注意事項:

    1> 從網絡上下載html頁面的過程應放在工做線程(後臺線程)中     2> html下載成功後渲染出html的步驟應放在UI主線程,否則WebView載入網頁過程會easy報錯
相關文章
相關標籤/搜索