WebView想說愛你不容易啊

zryd1357 7年前發布 | 17K 次閱讀 安卓開發 Android開發 移動開發

為什么要使用WebView

隨著app業務的不斷深入發展,只靠著原生代碼來堆砌功能是不現實,畢竟開發的時長會增加,而且同時需要開發iOS和Android兩套,并且,如果在UI上改變了一丁點,都需要提包(雖然Android現在可以進行熱更新,但是熱更新不是100%能生效的,其中的原理只要了解過的人都會知道的),最終我們會選擇使用原生嵌套H5的方式進行開發,這樣,既可以隨時更改UI,也可以無限制的進行功能擴展,然后,我們就要使用到Android的WebView了,這個讓我們痛并快樂著的控件。

現在的手機高度定制,多多少少都會對系統原生的代碼進行了修改和添加的,不同的手機的WebView呈現出來的效果也是不同的,可以說是五彩繽紛了,所以我懂Android開發者的痛苦。接下來我就具體去講解我在項目中使用WebView的經驗,不喜勿噴哈。

使用

一開始相信大家都是直接在布局文件中添加WebView控件,當然我一開始也是這樣做的,就是為了簡單,而且也不知道這樣會出現什么問題。

<WebView     
 
    android:id="@+id/web_view"     
 
    android:layout_width="match_parent"     
 
    android:layout_height="match_parent"/>  

直接就這樣添加了一個WebView,發現也沒什么問題啊,一樣可以顯示,什么都是正常的啊。在重復打開有WebView的頁面時,你會發現,應用的內存會不斷升高,銷毀了之后也不會降下來,點擊GC也降不下來,這樣就出現了內存泄漏了,這時你就會發現,這樣使用WebView是不正確的,那么最好方式是如何使用呢?

那就是在代碼中動態添加。

首先在布局文件中聲明一個parent布局

<LinearLayout 
 
android:id="@+id/web_view" 
 
android:layout_width="match_parent" 
 
android:layout_height="wrap_content" 
 
android:orientation="horizontal" 
 
android:scrollbars="none" />  

然后在代碼中,把WebView當做其子View添加進去

WebView webView = new WebView(context); 
 
webViewLayout.addView(webView);  

網上很多人說這個context應該用application的,我覺得是不對的,如果你的WebView需要彈出一個dialog呢?還有其他的不可預估的問題的,最好還是用當前的activity的Context是最合適的。

上面說的是如何把WebView添加進來進行使用,然后到底它有哪些屬性是我們在開發中需要使用到的呢?

webView.loadUrl("www.baidu.com");//WebView加載的網頁使用loadUrl 
 
WebSettings webSettings = webView.getSettings();//獲得WebView的設置 
 
webSettings.setUseWideViewPort(true);// 設置此屬性,可任意比例縮放 
 
webSettings.setLoadWithOverviewMode(true);//適配 
 
webSettings.setJavaScriptEnabled(true);  //支持js 
 
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);  //設置 緩存模式 
 
webSettings.setDomStorageEnabled(true);// 開啟 DOM storage API 功能 
 
webSettings.setDatabaseEnabled(true);//開啟 database storage API 功能 
 
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);//HTTPS,注意這個是在LOLLIPOP以上才調用的 
 
webSettings.setAppCacheEnabled(true);//開啟 Application Caches 功能 
 
webSettings.setBlockNetworkImage(true);//關閉加載網絡圖片,在一開始加載的時候可以設置為true,當加載完網頁的時候再設置為false  

上面是使用WebView中最基礎的設置,相信在開發過程中都會進行如上的設置的。

webView.setWebChromeClient(new WebChromeClient() {     
 
     @Override    
 
     public void onProgressChanged(WebView view, int newProgress) { 
 
         //加載的進度 
 
     } 
 
     @Override 
 
     public void onReceivedTitle(WebView view, String title) {    
 
         //獲取WebView的標題 
 
     } 
 
    @Override 
 
    public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {     
 
        return super.onJsAlert(view, url, message, result); 
 
        //Js 彈框 
 
    } 
 
    @Override 
 
    public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {    
 
        AlertDialog.Builder b = new AlertDialog.Builder(IllegalQueryActivity.this);     
 
        b.setTitle("刪除");     
 
        b.setMessage(message);     
 
        b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {         
 
            @Override         
 
            public void onClick(DialogInterface dialog, int which) {             
 
                result.confirm();         
 
            }     
 
        });     
 
        b.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {         
 
            @Override         
 
            public void onClick(DialogInterface dialog, int which) {             
 
                result.cancel();         
 
            }     
 
        });     
 
        b.create().show();     
 
        return true; 
 
    } 
 
}); 
 
webView.setWebViewClient(new WebViewClient() {     
 
    @Override     
 
    public boolean shouldOverrideUrlLoading(WebView view, String url) {         
 
       //需要設置在當前WebView中顯示網頁,才不會跳到默認的瀏覽器進行顯示 
 
       return true;    
 
    }     
 
    @Override     
 
    public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { 
 
        super.onReceivedError(view, request, error); 
 
        //加載出錯了 
 
    }    
 
    @Override     
 
    public void onPageFinished(WebView view, String url) {         
 
        super.onPageFinished(view, url); 
 
        //加載完成 
 
    } 
 
}); 
 
webView.setDownloadListener(new DownLoadListener());//下載監聽 
 
private class DownLoadListener implements DownloadListener {    
 
    @Override    
 
    public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {       
 
    } 
 
}  

然后就是WebView跟JS的交互了

webView.addJavascriptInterface(new WebAppInterface(this), "WebJs"); 
 
public class WebAppInterface {  
 
    Context mContext;     
 
    public WebAppInterface(Context c) {         
 
        mContext = c;     
 
    }     
 
    @JavascriptInterface     
 
    public void method() { 
 
    } 
 
} 
 
webView.loadUrl("javascript:jsMethod()");//這是WebView最簡單的調用JS的方法  

當activity執行生命周期的時候,這里需要注意的是在onDestroy的時候,需要銷毀WebView,不然也會出現內存泄漏的。

@Overrideprotected void onPause() {     
 
    super.onPause();     
 
    if (webView != null) {         
 
        webView.onPause();     
 
    } 
 
} 
 
@Override 
 
protected void onResume() {     
 
    super.onResume();     
 
    if (webView != null) {         
 
        webView.onResume();     
 
    } 
 
} 
 
@Override 
 
protected void onDestroy() {         
 
    if (webView != null) {         
 
        webView.clearCache(true); //清空緩存    
 
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {             
 
            if (webViewLayout != null) {                 
 
                webViewLayout.removeView(webView);             
 
            }             
 
        webView.removeAllViews();             
 
        webView.destroy();         
 
    }else {             
 
        webView.removeAllViews();             
 
        webView.destroy();             
 
        if (webViewLayout != null) {                 
 
            webViewLayout.removeView(webView);            
 
        }         
 
     }   
 
     webView = null;     
 
  }    
 
}  

可以看到上面的onDestroy方法中對系統的版本進行了判斷,那是因為我在不同的版本中進行了測試,如果低于5.0版本的WebView中,如果先在parent中remove了WebView,那WebView將無法進行destroy了,這樣就會造成內存的泄漏,下來你們可以自己去嘗試一下這個說法是不是正確的。

現在還遇到的一個問題就是,當WebView嵌套在ScrollView中時,某些機型會出現閃屏的問題,單獨WebView的時候是不會出現的,把硬件加速關閉了之后,對用戶的體驗又不好,所以暫時還未想到比較好的解決方案,所以還是建議不要在ScrollView中嵌套WebView這樣的控件。

 

來自:http://mobile.51cto.com/app-show-538256.htm

 

 本文由用戶 zryd1357 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!