Android學習之 WebView使用小結

來源:互聯網
上載者:User

標籤:android   webview   

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


網上關於HTML5規範定稿的一篇見解文章:

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


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


一、WebView基於webkit引擎展現web頁面的控制項,使用前需要在Android Manifest file中配置internet存取權限,否則提示頁面無法訪問。

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


二、WebView屬性的設定
  1、設定WebSettings類
     WebSettings用來對WebView的配置進行配置和管理,比如是否可以進行檔案操作、緩衝的設定、頁面是否支援放大和縮小、是否允許使用資料庫api、字型及文字編碼設定、是否允許js指令碼運行、是否允許圖片自動載入、是否允許資料及密碼儲存等等
     範例程式碼如下:

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顯示圖片,可使用這個參數 設定網頁布局類型:  * 1、LayoutAlgorithm.NARROW_COLUMNS :適應內容大小  * 2、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(); 
  2、設定WebChromeClient子類
      WebChromeClient會在一些影響瀏覽器ui互動動作發生時被調用,比如WebView關閉和隱藏、頁面載入進展、js確認框和警告框、js載入前、js操作逾時、webView獲得焦點等等

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

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


三、設定當前網頁的連結仍在WebView中跳轉,而不是跳到手機瀏覽器裡顯示,
       在WebViewClient的子類中重寫shouldOverrideUrlLoading函數  代碼如下:

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處理

四、設定開始載入網頁、載入完成、載入錯誤時處理
   在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);    }  });

五、處理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);  // 可做其他處理    } }); 

六、顯示頁面載入進度
   在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的整數

七、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的上次訪問頁面

八、使用addJavascriptInterface完成和js互動
1、Js中調Native本地Java方法
  設定webView的addJavascriptInterface方法,該方法有兩個參數,第一個參數為被綁定到js中的類執行個體,第二個參數為在js中暴露的類別名,在js中引用java對象就是用這個名字
在Native Java代碼如下:

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>
2、Java調Js方法
比如在HTML中有如下Js函數

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

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

九、WebView緩衝模式的設定
1、網頁資料緩衝
當使用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);  

2、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);

十、加快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()方法添加如下代碼:

@Overridepublic void onPageFinished(WebView view, String url) {    if(!webView.getSettings().getLoadsImagesAutomatically()) {        webView.getSettings().setLoadsImagesAutomatically(true);    }}
從上面的代碼,可以看出我們對系統API在19以上的版本作了相容。因為4.4以上系統在onPageFinished時再恢複圖片載入時,如果存在多張圖片引用的是相同的src時,會只有一個image標籤得到載入,因而對於這樣的系統我們就先直接載入。


十一、WebView硬體加速導致頁面渲染閃爍問題解決方案
    關於Android硬體加速 開始於Android 3.0 (API level 11),在四個層級上開啟/關閉硬體加速
    1、Application層級:為整個應用程式開啟硬體加速,在AndroidManifest中加入如下配置

<application android:hardwareAccelerated="true" ...>
   2、Activity層級:控制每個activity是否開啟硬體加速,只需在activity元素中添加android:hardwareAccelerated屬性即可

<activity android:hardwareAccelerated="true" ...>
   3、Window層級:註:目前還不支援在Window層級上關閉硬體加速

getWindow().setFlags(    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
   4、View層級:運行時單個view硬體加速,目前Android還不支援在View層級開啟硬體加速  代碼如下:

mView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    

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

     我們開啟硬體加速後,WebView渲染頁面更加快速,拖動也更加順滑。但有個副作用就是容易會出現頁面載入白塊同時介面閃爍現象。解決這個問題的方法是設定WebView暫時關閉硬體加速 代碼如下:

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

十二、其他注意事項:
    1> 從網路上下載html頁面的過程應放在背景工作執行緒(後台線程)中
    2> html下載成功後渲染出html的步驟應放在UI主線程,不然WebView載入網頁過程會容易報錯












Android學習之 WebView使用小結

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.