Android WebView使用详解

一、简介

WebView是一个基于webkit引擎、展现web页面的控件,(注:android的Webview在低版本和高版本采用了不同的webkit版本内核,4.4后直接使用了Chrome。)

二、作用

     2.1、显示和渲染Web页面
     2.2、直接使用html文件(网络上或本地assets中)作布局
     2.3、可和JavaScript交互调用

三、WebView常用方法介绍

    3.1、loadUrl()

           //方式1. 加载一个网页:
            webView.loadUrl("http://www.google.com/");
           //方式2:加载apk包中的html页面
            webView.loadUrl("file:///android_asset/test.html");
           //方式3:加载手机本地的html页面
            webView.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");
    3.2、loadData()

           //加载 HTML 页面的一小段内容
           webView.loadData(String data, String mimeType, String encoding)
           // 参数1:需要截取展示的内容(不能包含特殊字符:#、%、\,?)
           // 参数2:展示内容的类型
           // 参数3:字节码
    3.3、loadDataWithBaseURL()

          // 显示文字与图片内容(支持多个模拟器版本) 
         webview.loadDataWithBaseURL(String baseUrl,String data,String mimeType,String encoding,String historyUrl);
         // 参数1:相关资源的相对根路径
         // 参数2:需要截取展示的内容(不能包含特殊字符:#、%、\,?)
         // 参数3:展示内容的类型
         // 参数4:字节码
         // 参数5:也可以指定历史Url

    3.4、其他设置方法

         setJavaScriptEnabled(true);  //支持js
         setPluginsEnabled(true);  //支持插件 
         setUseWideViewPort(false);  //将图片调整到适合webview的大小 
         setSupportZoom(true);  //支持缩放 
         setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN); //支持内容重新布局  
         supportMultipleWindows();  //多窗口 
         setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);  //关闭webview中缓存 
         setAllowFileAccess(true);  //设置可以访问文件 
         setNeedInitialFocus(true); //当webview调用requestFocus时为webview设置节点
         webview webSettings.setBuiltInZoomControls(true); //设置支持缩放 
         setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口 
         setLoadWithOverviewMode(true); // 缩放至屏幕的大小
         setLoadsImagesAutomatically(true);  //支持自动加载图片

四、WebView常用类介绍

     4.1、WebSettings类

          //声明WebSettings子类
         WebSettings webSettings = webView.getSettings();

         //如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
         webSettings.setJavaScriptEnabled(true);  
         // 若加载的 html 里有JS 在执行动画等操作,会造成资源浪费(CPU、电量)
         // 在 onStop 和 onResume 里分别把 setJavaScriptEnabled() 给设置成 false 和 true 即可

         //支持插件
         webSettings.setPluginsEnabled(true); 

         //设置自适应屏幕,两者合用
         webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小 
         webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小

         //缩放操作
         webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
         webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
         webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件

         //其他细节操作
         webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存 
         webSettings.setAllowFileAccess(true); //设置可以访问文件 
         webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口 
         webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
         webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式

     4.2、WebViewClient类

    webview.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                return super.shouldOverrideUrlLoading(view, url);
            }

            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {

            }

            @Override
            public void onPageFinished(WebView view, String url) {

            }

            @Override
            public void onLoadResource(WebView view, String url) {
                super.onLoadResource(view, url);
            }

            @Override
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                super.onReceivedError(view, request, error);
            }
      });
           4.2.1 shouldOverrideUrlLoading() 方法

              打开网页时不调用系统浏览器, 而是在本WebView中显示;在网页上的所有加载都经过这个方法,这个函数我们可以做很多操作。

       webView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                  view.loadUrl(url);
               return true;
            }
        });

          4.2.2  onPageStarted() 方法

              开始载入页面调用的,我们可以设定一个loading的页面,告诉用户程序在等待网络响应

       webView.setWebViewClient(new WebViewClient(){
            @Override
            public void  onPageStarted(WebView view, String url, Bitmap favicon) {
                //设定加载开始的操作
            }
       });

          4.2.3 onPageFinished() 方法
              在页面加载结束时调用。我们可以关闭loading 条,切换程序动作

       webView.setWebViewClient(new WebViewClient(){
            @Override
            public void onPageFinished(WebView view, String url) {
                 //设定加载结束的操作
            }
       });

          4.2.4 onLoadResource() 方法

              在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次

       webView.setWebViewClient(new WebViewClient(){
           @Override
           public boolean onLoadResource(WebView view, String url) {
                //设定加载资源的操作
           }
       });

         4. 2.5 onReceivedError() 方法

              加载页面的服务器出现错误时(如404)调用

       webView.setWebViewClient(new WebViewClient(){
            @Override
            public void onReceivedError(WebView view, int errorCode, String description, String failingUrl){
                 switch(errorCode){
                    case HttpStatus.SC_NOT_FOUND:
                         view.loadUrl("file:///android_assets/error_handle.html");
                    break;
                 }
            }
        });

          4.2.6 onReceivedSslError() 方法

              处理https请求出错

            (注:当使用webview控件请求时遇到了诸如404这类的错误的时候,这时候我们的app就需要加载一个本地的错误提示页面,即webview如何加载一个本地的页面)

       webView.setWebViewClient(new WebViewClient() {    
            @Override    
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {    
                 handler.proceed();    //表示等待证书响应
                 // handler.cancel();      //表示挂起连接,为默认方式
                 // handler.handleMessage(null);    //可做其他处理
            }    
       });

     4.3、WebChromeClient类

      webview.setWebChromeClient(new WebChromeClient(){
            @Override
            public void onReceivedTitle(WebView view, String title) {
                super.onReceivedTitle(view, title);
            }

            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
            }

            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                return super.onJsAlert(view, url, message, result);
            }

            @Override
            public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
                return super.onJsConfirm(view, url, message, result);
            }

            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                return super.onJsPrompt(view, url, message, defaultValue, result);
            }
       });
         4.3.1 onReceivedTitle() 方法

               获取Web页中的标题

       webview.setWebChromeClient(new WebChromeClient(){
            @Override
            public void onReceivedTitle(WebView view, String title) {
                 titleview.setText(title);
            } 
        });

         4.3.2 onProgressChanged() 方法

                获得网页的加载进度并显示

        webview.setWebChromeClient(new WebChromeClient(){
             @Override
             public void onProgressChanged(WebView view, int newProgress) {
                  if (newProgress < 100) {
                       String progress = newProgress + "%";
                       progress.setText(progress);
                  } else if (newProgress == 100) {
                       String progress = 100+ "%";
                       progress.setText(progress);
	          }
             }
        });

         4.3.3 onJsAlert() 方法

               支持javascript的警告框

       webview.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onJsAlert(WebView view, String url, String message, final JsResult result)  {
                 new AlertDialog.Builder(MainActivity.this)
                   .setTitle("JsAlert")
                   .setMessage(message)
                   .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                         @Override
                         public void onClick(DialogInterface dialog, int which) {
                               result.confirm();
                         }
                 })
                .setCancelable(false)
                .show();
             return true;
            }
        });

         4.3.4 onJsConfirm() 方法

               支持javascript的确认框

       webview.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onJsConfirm(WebView view, String url, String message, final JsResult result) {
                new AlertDialog.Builder(MainActivity.this)
                .setTitle("JsConfirm")
                .setMessage(message)
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                      @Override
                      public void onClick(DialogInterface dialog, int which) {
                           result.confirm();
                      }
                })
               .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                      @Override
                      public void onClick(DialogInterface dialog, int which) {
                           result.cancel();
                      }
                 })
                .setCancelable(false)
                .show();
              // 返回布尔值:判断点击时确认还是取消
              // true表示点击了确认;false表示点击了取消;
             return true;
             }
        });

         4.3.5 onJsPrompt() 方法

               支持javascript输入框

       webview.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result) {
                 final EditText et = new EditText(MainActivity.this);
                 et.setText(defaultValue);
                 new AlertDialog.Builder(MainActivity.this)
                 .setTitle(message)
                 .setView(et)
                 .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                       @Override
                       public void onClick(DialogInterface dialog, int which) {
                            result.confirm(et.getText().toString());
                       }
                  })
                 .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                       @Override
                       public void onClick(DialogInterface dialog, int which) {
                            result.cancel();
                       }
                  })
                 .setCancelable(false)
                 .show();
              return true;
              }
        });

五、WebView的生命周期方法

    5.1 webView.onResume() ;
         激活WebView为活跃状态,能正常执行网页的响应
    5.2 webView.onPause();
         当页面被失去焦点被切换到后台不可见状态,需要执行onPause
         通过onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。
    5.4 webView.pauseTimers()
         当应用程序(存在webview)被切换到后台时,这个方法不仅仅针对当前的webview而是全局的全应用程序的webview
         它会暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。
    5.5 webView.resumeTimers();
         恢复pauseTimers状态
    5.6 webView.destroy();
         在关闭了Activity时,如果Webview的音乐或视频,还在播放。就必须销毁Webview
         但是注意:webview调用destory时,webview仍绑定在Activity上
         这是由于自定义webview构建时传入了该Activity的context对象
         因此需要先从父容器中移除webview,然后再销毁webview: rootLayout.removeView(webView)

六、关于前进和后退的方法

    6.1 前进
         //是否可以前进                     
        webview.canGoForward()
        //前进网页
        webview.goForward()
    6.2 后退
        //是否可以后退
        webview.canGoBack() 
        //后退网页
        webview.goBack()
    6.3 webview.goBackOrForward()
         以当前的index为起始点前进或者后退到历史记录中指定的steps,如果steps为负数则为后退,正数则为前进
    6.4 Back键控制网页后退
         在不做任何处理前提下,浏览网页时点击系统的“Back”键,整个浏览器会调用 finish()而结束自身
         如果想点击返回后,是网页回退而不是推出浏览器,则需要这么解决:

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

七、缓存数据的操作

    7.1 设置缓存的方法

         7.1.1 设置缓存的优先级:
                  WebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 
                      //缓存模式如下:
                      //LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
                      //LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
                      //LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
                     //LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
         7.1.2 结合使用(离线加载)例子:
         if (NetStatusUtil.isConnected(getApplicationContext())) {
            webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);//根据cache-control决定是否从网络上取数据。
         } else {
            webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);//没网,则从本地获取,即离线加载
         }
        webSettings.setDomStorageEnabled(true); // 开启 DOM storage API 功能
        webSettings.setDatabaseEnabled(true);   //开启 database storage API 功能
        webSettings.setAppCacheEnabled(true);//开启 Application Caches 功能
        String cacheDirPath = getFilesDir().getAbsolutePath() + APP_CACAHE_DIRNAME;
        webSettings.setAppCachePath(cacheDirPath); //设置  Application Caches 缓存目录
     (注:1、每个 Application 只调用一次 WebSettings.setAppCachePath(),WebSettings.setAppCacheMaxSize()
                 2、当加载 html 页面时,WebView会在/data/data/包名目录下生成database与cache两个文件夹请求的 URL记录保存在 WebViewCache.db,而 URL的内容是保存在 WebViewCache 文件夹下)

    7.2 清除缓存的方法

          7.2.1 webview.clearCache(true);
                    清除网页访问留下的缓存,由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
          7.2.2 webview.clearHistory()
                    清除当前webview访问的历史记录,只会webview访问历史记录里的所有记录除了当前访问记录.
          7.2.3 webview.clearFormData();
                   仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据

八、避免WebView内存泄露

     8.1 在Activity中创建,使用getApplicationgContext()对象上下文
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
        webView = new WebView(getApplicationContext());
        webView.setLayoutParams(params);
        mLayout.addView(webView);

     8.2 在 Activity 销毁( WebView )的时候,先让 WebView 加载null内容,然后移除 WebView,再销毁 WebView,最后置空。

    @Override
    protected void onDestroy() {
        if (webView != null) {
            webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
            webView.clearHistory();

            ((ViewGroup) webView.getParent()).removeView(webView);
            webView.destroy();
            webView = null;
        }
        super.onDestroy();
    }

九、优点

     9.1 开发成本低,可以适配多种平台的设备

     9.2 迭代更新成本低,可以快速的实现更新的内容全覆盖

十、案例

步棸1 :添加网络权限

<uses-permission android:name="android.permission.INTERNET"/>

步棸2:布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <!-- 获取网站的标题-->
    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="获取网站的标题" />

    <!--开始加载提示-->
    <TextView
        android:id="@+id/text_beginLoading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="" />

    <!--获取加载进度-->
    <TextView
        android:id="@+id/text_Loading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="" />

    <!--结束加载提示-->
    <TextView
        android:id="@+id/text_endLoading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="" />

    <!--显示网页区域-->
    <WebView
        android:id="@+id/webView1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_marginTop="10dp" />

</LinearLayout>

步棸3:MainActivity.class

import android.graphics.Bitmap;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    WebView mWebview;
    WebSettings mWebSettings;
    TextView beginLoading, endLoading, loading, mtitle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mWebview = (WebView) findViewById(R.id.webView1);
        beginLoading = (TextView) findViewById(R.id.text_beginLoading);
        endLoading = (TextView) findViewById(R.id.text_endLoading);
        loading = (TextView) findViewById(R.id.text_Loading);
        mtitle = (TextView) findViewById(R.id.title);
        mWebSettings = mWebview.getSettings();
        mWebview.loadUrl("http://www.baidu.com/");

        //设置WebViewClient类
        mWebview.setWebViewClient(new WebViewClient() {
            //设置不用系统浏览器打开,直接显示在当前Webview
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }

            //设置加载前的函数
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                beginLoading.setText("开始加载了");

            }

            //设置结束加载函数
            @Override
            public void onPageFinished(WebView view, String url) {
                endLoading.setText("结束加载了");

            }
        });


        //设置WebChromeClient类
        mWebview.setWebChromeClient(new WebChromeClient() {


            //获取网站标题
            @Override
            public void onReceivedTitle(WebView view, String title) {
                System.out.println("标题在这里");
                mtitle.setText(title);
            }

            //获取加载进度
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                if (newProgress < 100) {
                    String progress = newProgress + "%";
                    loading.setText(progress);
                } else if (newProgress == 100) {
                    String progress = newProgress + "%";
                    loading.setText(progress);
                }
            }
        });
    }

    //点击返回上一页面而不是退出浏览器
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && mWebview.canGoBack()) {
            mWebview.goBack();
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

    //销毁Webview
    @Override
    protected void onDestroy() {
        if (mWebview != null) {
            mWebview.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
            mWebview.clearHistory();

            ((ViewGroup) mWebview.getParent()).removeView(mWebview);
            mWebview.destroy();
            mWebview = null;
        }
        super.onDestroy();
    }
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值