WebView想說愛你不容易啊
為什么要使用WebView
隨著app業(yè)務(wù)的不斷深入發(fā)展,只靠著原生代碼來堆砌功能是不現(xiàn)實,畢竟開發(fā)的時長會增加,而且同時需要開發(fā)iOS和Android兩套,并且,如果在UI上改變了一丁點,都需要提包(雖然Android現(xiàn)在可以進行熱更新,但是熱更新不是100%能生效的,其中的原理只要了解過的人都會知道的),最終我們會選擇使用原生嵌套H5的方式進行開發(fā),這樣,既可以隨時更改UI,也可以***制的進行功能擴展,然后,我們就要使用到Android的WebView了,這個讓我們痛并快樂著的控件。
現(xiàn)在的手機高度定制,多多少少都會對系統(tǒng)原生的代碼進行了修改和添加的,不同的手機的WebView呈現(xiàn)出來的效果也是不同的,可以說是五彩繽紛了,所以我懂Android開發(fā)者的痛苦。接下來我就具體去講解我在項目中使用WebView的經(jīng)驗,不喜勿噴哈。
使用
一開始相信大家都是直接在布局文件中添加WebView控件,當然我一開始也是這樣做的,就是為了簡單,而且也不知道這樣會出現(xiàn)什么問題。
- <WebView
 - android:id="@+id/web_view"
 - android:layout_width="match_parent"
 - android:layout_height="match_parent"/>
 
直接就這樣添加了一個WebView,發(fā)現(xiàn)也沒什么問題啊,一樣可以顯示,什么都是正常的啊。在重復(fù)打開有WebView的頁面時,你會發(fā)現(xiàn),應(yīng)用的內(nèi)存會不斷升高,銷毀了之后也不會降下來,點擊GC也降不下來,這樣就出現(xiàn)了內(nèi)存泄漏了,這時你就會發(fā)現(xiàn),這樣使用WebView是不正確的,那么***方式是如何使用呢?
那就是在代碼中動態(tài)添加。
首先在布局文件中聲明一個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);
 
網(wǎng)上很多人說這個context應(yīng)該用application的,我覺得是不對的,如果你的WebView需要彈出一個dialog呢?還有其他的不可預(yù)估的問題的,***還是用當前的activity的Context是最合適的。
上面說的是如何把WebView添加進來進行使用,然后到底它有哪些屬性是我們在開發(fā)中需要使用到的呢?
- webView.loadUrl("www.baidu.com");//WebView加載的網(wǎng)頁使用loadUrl
 - WebSettings webSettings = webView.getSettings();//獲得WebView的設(shè)置
 - webSettings.setUseWideViewPort(true);// 設(shè)置此屬性,可任意比例縮放
 - webSettings.setLoadWithOverviewMode(true);//適配
 - webSettings.setJavaScriptEnabled(true); //支持js
 - webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); //設(shè)置 緩存模式
 - webSettings.setDomStorageEnabled(true);// 開啟 DOM storage API 功能
 - webSettings.setDatabaseEnabled(true);//開啟 database storage API 功能
 - webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);//HTTPS,注意這個是在LOLLIPOP以上才調(diào)用的
 - webSettings.setAppCacheEnabled(true);//開啟 Application Caches 功能
 - webSettings.setBlockNetworkImage(true);//關(guān)閉加載網(wǎng)絡(luò)圖片,在一開始加載的時候可以設(shè)置為true,當加載完網(wǎng)頁的時候再設(shè)置為false
 
上面是使用WebView中最基礎(chǔ)的設(shè)置,相信在開發(fā)過程中都會進行如上的設(shè)置的。
- 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) {
 - //需要設(shè)置在當前WebView中顯示網(wǎng)頁,才不會跳到默認的瀏覽器進行顯示
 - 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());//下載監(jiān)聽
 - 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最簡單的調(diào)用JS的方法
 
當activity執(zhí)行生命周期的時候,這里需要注意的是在onDestroy的時候,需要銷毀WebView,不然也會出現(xiàn)內(nèi)存泄漏的。
- @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方法中對系統(tǒng)的版本進行了判斷,那是因為我在不同的版本中進行了測試,如果低于5.0版本的WebView中,如果先在parent中remove了WebView,那WebView將無法進行destroy了,這樣就會造成內(nèi)存的泄漏,下來你們可以自己去嘗試一下這個說法是不是正確的。
現(xiàn)在還遇到的一個問題就是,當WebView嵌套在ScrollView中時,某些機型會出現(xiàn)閃屏的問題,單獨WebView的時候是不會出現(xiàn)的,把硬件加速關(guān)閉了之后,對用戶的體驗又不好,所以暫時還未想到比較好的解決方案,所以還是建議不要在ScrollView中嵌套WebView這樣的控件。















 
 
 

 
 
 
 