中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android中WebView的基本配置與填坑記錄大全

發布時間:2020-09-10 14:18:35 來源:腳本之家 閱讀:279 作者:daisy 欄目:移動開發

前言

在應用程序開發過程中,經常會采用webview來展現某些界面,這樣就可以不受發布版本控制,實時更新,遇到問題可以快速修復。

但是在Android開發中,由于Android版本分化嚴重,每一個版本針對webview都有部分更改,因此在開發過程中會遇到各種各樣的坑,下面這篇就來給大家介紹關于Android中WebView的基本配置與填坑記錄,話不多說了,來一起看看詳細的介紹吧。

基本配置

// 硬件加速
getActivity().getWindow().setFlags(
 WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
 WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
// WebView 配置
WebSettings webSettings = mWebView.getSettings();
// 生命周期
mWebView.onPause(); // 通過 onPause 動作通知內核暫停所有的動作,如 DOM 的解析、plugin 的執行、JavaScript 執行等
mWebView.onResume(); // 恢復 WebView,能正常執行網頁的響應
((ViewGroup) mWebView.getParent()).removeView(mWebView);
mWebView.destroy(); // 當 Activity 要 destroy 時,應先將 WebView 移除,再 destroy 掉
// 前進后退
if (mWebView.canGoBack()) {
 mWebView.goBack();
}
if (mWebView.canGoForward()) {
 mWebView.goForward();
}
// 緩存相關
mWebView.clearCache(true); // 清除緩存
mWebView.clearHistory(); // 清除歷史
mWebView.clearFormData(); // 清除表單數據
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);// 設置緩存模式
// 緩存模式
LOAD_DEFAULT: 默認,根據 cache-control 決定是否從網絡上取數據
LOAD_NORMAL: API level 17 中已經廢棄, 從API level 11開始作用同 LOAD_DEFAULT 模式
LOAD_CACHE_ELSE_NETWORK: 只要本地有,無論是否過期,或者 no-cache,都使用緩存中的數據
LOAD_NO_CACHE: 不使用緩存,只從網絡獲取數據
LOAD_CACHE_ONLY: 不使用網絡,只讀取本地緩存數據
// js 相關
webSettings.setJavaScriptEnabled(true); // 支持 js。如果碰到后臺無法釋放 js 導致耗電,應在 onStop 和 onResume 里分別設成 false 和 true 
mWebView.addJavascriptInterface(new WebAppInterface(this), "android"); // js 接口
webSettings.setPluginsEnabled(true); // 支持插件
// 設置自適應屏幕,兩者合用
webSettings.setUseWideViewPort(true); // 將圖片調整到適合 WebView 的大小 
webSettings.setLoadWithOverviewMode(true); // 縮放至屏幕的大小
// 縮放操作
webSettings.setSupportZoom(true); // 支持縮放,默認為 true
webSettings.setBuiltInZoomControls(true); // 設置內置的縮放控件,若為 false,則該 WebView 不可縮放
webSettings.setDisplayZoomControls(false); // 隱藏原生的縮放控件

填坑記錄

1、WebViewClient 類常用方法

mWebView.setWebViewClient(new MyWebViewClient());

shouldOverrideUrlLoading()

在網頁上的所有加載都經過這個方法,這個函數我們可以做很多操作。

onPageStarted()

開始載入頁面調用的,我們可以設定一個 loading 的頁面,告訴用戶程序在等待網絡響應。

onPageFinished()

在頁面加載結束時調用。我們可以關閉 loading 條,切換程序動作。

onLoadResource()

在加載頁面資源時會調用,每一個資源(比如圖片)的加載都會調用一次。

onReceivedError()

加載頁面出現錯誤時調用。

2、WebChromeClient 類常用方法

mWebView.setWebChromeClient(new MyWebChromeClient());

onProgressChanged()

獲得網頁的加載進度并顯示。

onReceivedTitle()

獲取 Web 頁中的標題。

onJsAlert()

支持 javascript 的警告框。

onJsConfirm()

支持 javascript 的確認框。

onJsPrompt()

支持 javascript 輸入框。

3、 Https 和 Http 混合模式

從 Android 5.0 開始,WebView 默認不支持同時加載 Https 和 Http 資源。

解決方法:在webview加載頁面之前,設置加載模式為 MIXED_CONTENT_ALWAYS_ALLOW

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
 webView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}

4、安全問題

addJavascriptInterface

Android 4.2 以前,要采用攔截 prompt() 的方式進行漏洞修復;Android 4.2 以后,只需要對被調用的函數以 @JavascriptInterface 進行注解。

searchBoxJavaBridge_、accessibility、accessibilityTraversal

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
 mWebView.removeJavascriptInterface("searchBoxJavaBridge_");
 mWebView.removeJavascriptInterface("accessibility");
 mWebView.removeJavascriptInterface("accessibilityTraversal");
}

密碼明文存儲漏洞

webSettings.setSavePassword(false);

5、替換 WebView 的加載錯誤頁面

@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
 super.onReceivedError(view, errorCode, description, failingUrl);
 showCustErrorPage();
}
private View mErrorView;
protected void showCustErrorPage() {
 // 移除WebView
 ViewGroup webParentView = (ViewGroup) mWebViewInstance.getParent();
 while (webParentView.getChildCount() > 0) {
 webParentView.removeViewAt(0);
 }
 // 生成自定義錯誤頁面
 if (mErrorView == null) {
 mErrorView = View.inflate(mContext, R.layout.webview_error, null);
 mErrorView.setOnClickListener(new View.OnClickListener() {
  public void onClick(View v) {
  showWebViewPage();
  mWebViewInstance.reload();
  }
 });
 }
 // 替換為錯誤頁面
 ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
  ViewPager.LayoutParams.FILL_PARENT, ViewPager.LayoutParams.FILL_PARENT);
 webParentView.addView(mErrorView, 0, lp);
}
protected void showWebViewPage() {
 // 移除自定義錯誤頁面
 ViewGroup webParentView = (ViewGroup) mErrorView.getParent();
 while (webParentView.getChildCount() > 0) {
 webParentView.removeViewAt(0);
 }
 // 替換為WebView
 ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
  ViewPager.LayoutParams.FILL_PARENT, ViewPager.LayoutParams.FILL_PARENT);
 webParentView.addView(mWebViewInstance, 0, lp);
}

6、WebView的內存泄露。

關于這個問題,我很難給你一個清晰的描述,你在谷歌里搜 webview lead memory 能搜到很多結果 甚至還有給谷歌提交的issue 哈哈,我也無法給出一個清晰的答案 在什么時候 什么版本那些手機上一定會出現內存泄露,

但是根據我自己的monkey結果來看,有時,webview內存泄露的情況還是很嚴重的,尤其是當你加載的頁面比較龐大的時候。解決方案 我查了很多也用了很多,但是都不太理想,最后看了下微信和qq的做法,試了一下是目前效果最好的,

就是 當你要用webview的時候,記得最好 另外單獨開一個進程 去使用webview 并且當這個 進程結束時,請手動調用System.exit(0)。

這是目前對于webview 內存泄露 最好的解決方案。使用此方法 所有因為webview引發的 資源無法釋放等問題 全部可以解決。

7、getSettings().setBuiltInZoomControls(true) 引發的crush。

這個方法調用以后 如果你觸摸屏幕 彈出那個提示框還沒消失的時候 你如果activity結束了 就會報錯了。3.0以上 4.4以下很多手機會出現這種情況

所以為了規避他,我們通常是在activity的onDestroy方法里手動的將webiew設置成 setVisibility(View.GONE)

8、onPageFinished 函數到底有用沒有?

多數開發者都是參考的http://stackoverflow.com/questions/3149216/how-to-listen-for-a-webview-finishing-loading-a-url-in-android 這個上面的高票答案。

但其實根據我自己觀察,這個函數并沒有什么卵用,有的時候是提前結束,有的時候就遲遲無法結束,你信這個函數 還不如信上帝,甚至于onProgressChanged這個函數

都比onPageFinished 要準一些。如果你的產品經理堅持你一定要實現這種功能的話,我建議你 提早結束他,否則卡在那用戶遲遲動不了 這種體驗不好。

有空的同學可以跟一下源碼,onPageFinished 在不同的內核里 調用的時機都不一樣。說實話 我也很醉。。。這個問題 有完美解決方案的 請知會我一下。。。

9、后臺無法釋放js 導致耗電。

這個可能很少有人知道,我也是被投訴過 才了解,在有的手機里,你如果webview加載的html里 有一些js 一直在執行比如動畫之類的東西,如果此刻webview 掛在了后臺

這些資源是不會被釋放 用戶也無法感知。。。導致一直占有cpu 耗電特別快,所以大家記住了,如果遇到這種情況 請在onstop和onresume里分別把setJavaScriptEnabled();

給設置成false和true。

10、如果實在不想用開額外進程的方式解決webview 內存泄露的問題,那么下面的方法很大程度上可以避免這種情況

public void releaseAllWebViewCallback() {
  if (android.os.Build.VERSION.SDK_INT < 16) {
   try {
    Field field = WebView.class.getDeclaredField("mWebViewCore");
    field = field.getType().getDeclaredField("mBrowserFrame");
    field = field.getType().getDeclaredField("sConfigCallback");
    field.setAccessible(true);
    field.set(null, null);
   } catch (NoSuchFieldException e) {
    if (BuildConfig.DEBUG) {
     e.printStackTrace();
    }
   } catch (IllegalAccessException e) {
    if (BuildConfig.DEBUG) {
     e.printStackTrace();
    }
   }
  } else {
   try {
    Field sConfigCallback = Class.forName("android.webkit.BrowserFrame").getDeclaredField("sConfigCallback");
    if (sConfigCallback != null) {
     sConfigCallback.setAccessible(true);
     sConfigCallback.set(null, null);
    }
   } catch (NoSuchFieldException e) {
    if (BuildConfig.DEBUG) {
     e.printStackTrace();
    }
   } catch (ClassNotFoundException e) {
    if (BuildConfig.DEBUG) {
     e.printStackTrace();
    }
   } catch (IllegalAccessException e) {
    if (BuildConfig.DEBUG) {
     e.printStackTrace();
    }
   }
  }
 }

在webview的 destroy方法里 調用這個方法就行了。

11、另外很多人 不知道webview 實際上有自己一套完整的cookie機制的,利用好這個 可以大大增加對客戶端的訪問速度。

Android中WebView的基本配置與填坑記錄大全

實際上cookie就是存放在這個表里的。

很多人都想要一個效果:網頁更新cookie 設置完cookie以后 不刷新頁面即可生效。這個在2.3以下和2.3以上要實現的方法不太一樣,所以要做一次兼容

public void updateCookies(String url, String value) {
  if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) { // 2.3及以下
   CookieSyncManager.createInstance(getContext().getApplicationContext());
  }
  CookieManager cookieManager = CookieManager.getInstance();
  cookieManager.setAcceptCookie(true);
  cookieManager.setCookie(url, value);
  if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
   CookieSyncManager.getInstance().sync();
  }
 }

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

行唐县| 同江市| 涞水县| 潢川县| 西昌市| 竹山县| 密山市| 嘉峪关市| 南溪县| 阳江市| 阿勒泰市| 富宁县| 玉环县| 嵩明县| 永宁县| 东海县| 泸溪县| 临猗县| 绥芬河市| 桐梓县| 淳化县| 长丰县| 什邡市| 北辰区| 湖口县| 潮州市| 松江区| 宝山区| 永寿县| 公安县| 依安县| 石泉县| 鄢陵县| 安新县| 新龙县| 乌拉特前旗| 舟曲县| 定远县| 南郑县| 满洲里市| 华蓥市|