前言:
今天修改專案中一個有關WebView使用的bug,激起了我總結WebView的動機,今天抽空做個總結。
混合開發相關部落格:
使用場景:
1.)新增許可權
<uses-permission android:name="android.permission.INTERNET" />
2.)佈局檔案
<WebView android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent" />
3.)資料載入
載入本地資源
webView.loadUrl("file:///android_asset/example.html");
載入網路資源
webView.loadUrl("www.xxx.com/index.html");
新增請求頭資訊
Map<String,String> map=new HashMap<String,String>();
map.put("User-Agent","Android"); webView.loadUrl("www.xxx.com/index.html",map);
也可以載入html片段
String data = " Html 資料";
webView.loadData(data, "text/html", "utf-8");
實測會發現loadData會導致中文亂碼,所以一般情況使用如下程式碼
String data = " Html 資料"; webView.loadDataWithBaseURL(null,data, "text/html", "utf-8",null);
4.)支援JavaScript
比如專案總js觸發一個native函式關閉Activity
設定支援JavaScript
WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true);//設定支援javascript webView.addJavascriptInterface(new JavaScriptInterface(), "xueleapp");
JavaScriptInterface 介面定義
public class JavaScriptInterface { @android.webkit.JavascriptInterface public void doTrainFinish() { finish(); } }
5.)設定WebViewClient 主要輔助WebView處理各種通知、請求事件
比如要實現WebView中連結在WebView內部跳轉
webView.setWebViewClient(new WebViewClient() { public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } });
除此之外WebViewClient更多的處理網頁的地址的解析和渲染,例如
onLoadResource//載入資源時響應
onPageStart//在載入頁面時響應
onPageFinish//在載入頁面結束時響應
onReceiveError//在載入出錯時響應
onReceivedHttpAuthRequest//獲取返回資訊授權請求
6.)設定WebChromeClient主要輔助WebView處理Javascript的對話方塊,網站圖示,網站title,載入進度等
比如載入進度獲取title
webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { if (newProgress == 100) { //網頁載入完成 } else { //網頁載入中 } } });
除了上面檢測進度之外還有
onCloseWindow//關閉WebView
onCreateWindow() //觸發建立一個新的視窗
onJsAlert //觸發彈出一個對話方塊
onJsPrompt //觸發彈出一個提示
onJsConfirm//觸發彈出確認提示
onProgressChanged //載入進度
onReceivedIcon //獲取網頁icon
onReceivedTitle//獲取網頁title
7.)設定網頁棧返回
webview會預設把瀏覽過去的網頁進行壓棧儲存,所以我們有時需要實現回退到上一目錄
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { if (webView.canGoBack()) { webView.goBack();//返回上一瀏覽頁面 return true; } else { finish();//關閉Activity } } return super.onKeyDown(keyCode, event); }
8.)WebView 快取控制
- 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 = webView.getSettings();
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
9.)WebView螢幕自適應
WebSettings webSettings = webView.getSettings(); webSettings.setUseWideViewPort(true); webSettings.setLoadWithOverviewMode(true);
10.)其他不常用設定
WebSettings webSettings = webView.getSettings(); webSettings.setSupportZoom(true); //支援縮放 webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); //支援內容重新佈局 webSettings.supportMultipleWindows(); //多視窗 webSettings.setAllowFileAccess(true); //設定可以訪問檔案 webSettings.setNeedInitialFocus(true); //當webview呼叫requestFocus時為webview設定節點 webSettings.setBuiltInZoomControls(true); //設定支援縮放 webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支援通過JS開啟新視窗 webSettings.setLoadsImagesAutomatically(true); //支援自動載入圖片
11.)知識擴充套件WebViewJSBridge
雖然谷歌也提供了js與native函式互相呼叫的方式,但是通過addjavascriptInterface這種方式在Android 4.2以下版本存在一定的安全隱患,在Android 4.2以上也需要加@JavascriptInterface註解,否則無法呼叫。基於上面的原因建議學習一下
WebViewJSBridge這個比較不錯的開源框架,地址:https://github.com/firewolf-ljw/WebViewJSBridge
12.)硬體加速
開啟硬體加速強制使用GPU渲染,確實給app流暢度帶來不小的提升,但是在使用過程中遇見webview閃爍,也有導致載入webView黑屏或者白屏
解決辦法:關閉硬體加速
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
這是把webview 中的硬體加速關閉。設定LAYER_TYPE_SOFTWARE後會把當前view轉為bitmap儲存。這樣就不能開多個webview,否則會報out of memory。
需要在在webview中加入如下程式碼
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { invalidate(); super.onMeasure(widthMeasureSpec, heightMeasureSpec); }