android webview 面試

總結

參考:https://www.jianshu.com/p/fd61e8f4049e

內核版本比較:https://www.cnblogs.com/gcczhongduan/p/4237959.html

x5 和 原生 比較:https://www.jianshu.com/p/d27f3379a4b7

使用心得

https://www.jianshu.com/p/3c94ae673e2a

https://www.jianshu.com/p/52ec85259ccc

1.WebView 中網頁的前進 / 後退

webView.goBack();//跳到上個頁面
webView.goForward();//跳到下個頁面
webView.canGoBack();//是否可以跳到上一頁(如果返回false,說明已經是第一頁)
webView.canGoForward();//是否可以跳到下一頁(如果返回false,說明已經是最後一頁)
  • 常見用法:Back 鍵控制網頁後退

問題:在不做任何處理前提下 ,瀏覽網頁時點擊系統的「 Back 」鍵,整個 Browser 會調用 finish()而結束自身
目標:點擊返回後,是網頁回退而不是推出瀏覽器
解決方案:在當前 Activity 中處理並消費掉該 Back 事件

public boolean onKeyDown(int keyCode, KeyEvent event) {
  if ((keyCode == KEYCODE_BACK) && mWebView.canGoBack()) { 
  	mWebView.goBack();
  	return true;
  }
  return super.onKeyDown(keyCode, event);
}

2.webView 緩存設置

//優先使用緩存: 
webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 
//緩存模式如下:
//LOAD_CACHE_ONLY: 不使用網絡,只讀取本地緩存數據
//LOAD_DEFAULT: (默認)根據cache-control決定是否從網絡上取數據。
//LOAD_NO_CACHE: 不使用緩存,只從網絡獲取數據.
//LOAD_CACHE_ELSE_NETWORK,只要本地有,無論是否過期,或者no-cache,都使用緩存中的數據。
 //不使用緩存: 
 webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);

3.webView 清除緩存

//清除網頁訪問留下的緩存
//由於內核緩存是全局的因此這個方法不僅僅針對webview而是針對整個應用程序.
webView.clearCache(true);

//清除當前webview訪問的歷史記錄
//只會webview訪問歷史記錄裏的所有記錄除了當前訪問記錄
webView.clearHistory();

//這個api僅僅清除自動完成填充的表單數據,並不會清除WebView存儲到本地的數據
webView.clearFormData();

另外一種方式:
//刪除緩存文件夾
File file = CacheManager.getCacheFileBaseDir(); 

if (file != null && file.exists() && file.isDirectory()) { 
for (File item : file.listFiles()) { 
    item.delete(); 
     } 
    file.delete(); 
} 
        
//刪除緩存數據庫
context.deleteDatabase("webview.db"); 
context.deleteDatabase("webviewCache.db");

4.cookies 設置,獲取和清除

  • Cookie 設置

代碼

CookieSyncManager.createInstance(this);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);

String cookie = "name=xxx;age=18";
cookieManager.setCookie(URL, cookie);
CookieSyncManager.getInstance().sync();
  • 獲取 Cookie

code:

CookieManager cookieManager = CookieManager.getInstance();
String cookie = cookieManager.getCookie(URL);
  • 清除 Cookie

code

CookieSyncManager.createInstance(context);  
CookieManager cookieManager = CookieManager.getInstance(); 
cookieManager.removeAllCookie();
CookieSyncManager.getInstance().sync();

5.webview 和 js 交互

  • JavaScript 調用 Android

code

WebSettings settings = mWebView.getSettings();
settings.setJavaScriptEnabled(true);//開啓JavaScript 

mWebView.loadUrl("file:///android_asset/keithxiaoy.html");//加載本地網頁
mWebView.setWebChromeClient(new WebChromeClient());//此行代碼可以保證JavaScript的Alert彈窗正常彈出

//核心方法, 用於處理JavaScript被執行後的回調
mWebView.addJavascriptInterface(new JsCallback() {

  @JavascriptInterface//注意:此處一定要加該註解,否則在4.1+系統上運行失敗
  @Override
  public void onJsCallback() {
      System.out.println("JavaScript調用Android啦");
  }
}, "keithxiaoy");//參1是回調接口的實現;參2是JavaScript回調對象的名稱

//定義回調接口
public interface JsCallback {
  public void onJsCallback();
}
  • Android 調用 JavaScript

code

  //直接使用webview加載js就可以了
  mWebView.loadUrl("javascript:wave()");
  • 附上 keithxiaoy.html 源碼

code

 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 </head>
 <script language="javascript">
     /* This function is invoked by the activity */
     function wave() {
         alert("Android調用JavaScript");
     }
 </script>
 <body>
     <!-- JavaScript調用Android代碼 -->
     <a onClick="window.demo.onJsCallback()"><div style="width:80px;
         margin:0px auto;
         padding:10px;
         text-align:center;
         border:2px solid #202020;" >
             ![](android_normal.png)<br>
             Click me!
     </div></a>
 </body>
</html>

面試題

1.WebView的內存泄露。

(1)微信和qq的做法:

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

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

(2)還有一種方法:

動態添加webview,對傳入webview中使用的Context使用弱引用,動態添加webview意思在佈局創建個viewGroup用來放置webview,Activity創建時add進來,在Activity停止時remove掉

2.WebView中使用setBuiltInZoomControls進行縮放並destroy webview時崩潰

問題描述:webview使用settings.setBuiltInZoomControls(true);進行控制縮放。由於某些原因需要在該activity的onDestroy方法裏面調用webView.destroy()。當進入該webview並且進行縮放操作時,退出該activity程序崩潰。

settings代碼如下:

settings = previewWebview.getSettings();
settings.setUseWideViewPort(true);
settings.setLoadWithOverviewMode(true);
settings.setBuiltInZoomControls(true);
settings.setDefaultTextEncodingName("gbk");

啓用後,用戶一旦觸摸屏幕,就會出現縮放控制圖標。這個圖標過上幾秒會自動消失,但在3.X系統上,如果圖標自動消失前退出當前Activity的話,就會報異常。

最終解決方法:

在Activity的onDestroy裏面加上這麼一句:web.setVisibility(View.GONE);把WebView設置爲GONE就可以了

3.後臺無法釋放js 導致耗電

這個可能很少有人知道,你如果webview加載的html裏 有一些js 一直在執行比如動畫之類的東西,如果此刻webview 掛在了後臺
這些資源是不會被釋放,用戶也無法感知,導致一直佔有cpu 耗電特別快,所以大家記住了,如果遇到這種情況 請在onstop和onresume裏分別把setJavaScriptEnabled();
給設置成false和true

4.Android中如何直接調用JS中的函數?

1.html中有js的方法callJs()裏面去調用alert()方法
2.webview.setWebChromeClient()中的onJsAlert()去處理JS對話框
3.webview.loadUrl(“javascript:callJS()”)去直接調用

問:如何通過evaluateJavascript直接調用JS中的函數?

webview.evaluateJavascript(“javascript:callJS()”)去調用JS的方法,並且在ValueCallback中能獲取JS的返回值。

建議混合使用上面的兩種交互方法

1.API < 18, Android 4.4以下使用loadUrl
2.API >=18, 使用evaluateJavascript

5.JS調用Android有哪些方法?

  1. 通過WebView的addJavascriptInterface()進行對象映射
  2. 通過WebViewClient的shouldOverrideUrlLoading()方法回調攔截url
  3. 通過WebChromeClient的onJsAlert()、onJsConfirm()、onJsPrompt()方法回調攔截JS對話框alert()、confirm()、prompt()消息

問:addJavascriptInterface()對象映射是如何使用的?

  • html中調用某對象的某個方法:如jsObject.hello(“js調用了android中的hello方法”);
  • Android中實現一個自定義類,具有方法hello(),該方法使用註解@JavascriptInterface
  • 進行映射webview.addJavascriptInterface(new 自定義類(), “jsObject”)
  • 加載js代碼:webview.loadUrl(“file:///android_asset/jsCallAndroid.html”);

問:addJavascriptInterface()存在嚴重漏洞

  • Android 4.2(17)版本開始通過@JavascriptInterface規避該漏洞
  • 該漏洞會導致攻擊者能執行任意Java對象的方法。

問:WebViewClient 中對url攔截

  • js中約定url協議
  • Android中在 shouldOverrideUrlLoading進行解析攔截

問:JS中如何獲得Android方法執行的返回值?

  • 只能採用特殊方法去處理
  • js定義一個方法,如命名爲returnResult(result)
  • android中通過mWebView.loadUrl(“javascript:returnResult(” + result + “)”);將方法返回值作爲參數傳入進去。

問:如何通過WebChromeClient的onJsAlert()\onJsConfirm()\onJsPrompt()方法回調攔截JS對話框alert()\confirm\prompt()消息

  • Android中通過WebChromeClient的onJsAlert()\onJsConfirm()\onJsPrompt()方法回調分別攔截JS對話框。
  • 本質是JS彈出對畫框,Android攔截了對話框,解析參數中的url等信息,去做事先約定好的任務。

總結

6.WebView初始化

問題描述:

1.當App首次打開時,默認是並不初始化瀏覽器內核的;只有當創建WebView實例的時候,纔會創建WebView的基礎框架。
所以與瀏覽器不同,App中打開WebView的第一步並不是建立連接,而是啓動瀏覽器內核。

2.在瀏覽器中,我們輸入地址時(甚至在之前),瀏覽器就可以開始加載頁面。而在客戶端中,客戶端需要先花費時間初始化WebView完成後,纔開始加載。

解決方法

方案1,全局WebView

在客戶端剛啓動時,就初始化一個全局的WebView待用,並隱藏;當用戶訪問了WebView時,直接使用這個WebView加載對應網頁,並展示。這種方法可以比較有效的減少WebView在App中的首次打開時間。當用戶訪問頁面時,不需要初始化WebView的時間。當然這也帶來了一些問題,包括:額外的內存消耗。頁面間跳轉需要清空上一個頁面的痕跡,更容易內存泄露。

方法2,客戶端代理數據請求
在客戶端初始化WebView的同時,直接由native開始網絡請求數據;當頁面初始化完成後,向native獲取其代理請求的數據。此方法雖然不能減小WebView初始化時間,但數據請求和WebView初始化可以並行進行,總體的頁面加載時間就縮短了;縮短總體的頁面加載時間:
還有其他各種優化的方式,不再一一列舉,總結起來都是圍繞兩點:
在使用前預先初始化好WebView,從而減小耗時。
在初始化的同時,通過Native來完成一些網絡請求等過程,使得WebView初始化不是完全的阻塞後續過程。

7.描述一下Webview的作用

WebView控件功能強大,除了具有一般View的屬性和設置外,還可以對url請求、頁面加載、渲染、頁面交互進行強大的處理。

8.WebView的內核是什麼

Android的Webview在低版本和高版本採用了不同的webkit版本內核,4.4後直接使用了Chrome。

9.描述一下WebView與js的交互方式

https://blog.csdn.net/carson_ho/article/details/64904691

10.描述一下WebView的緩存機制

https://www.jianshu.com/p/5e7075f4875f

11.關於WebView的優化你知道哪些

https://www.jianshu.com/p/95d4d73be3d1

12.有沒有用過第三方WebView組件?講一講優勢

https://www.jianshu.com/p/d3ef9c62b6c8

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章