什么是WebView?

WebView是Android中的原生UI控件,主要用于在app应用中方便地访问远程网页或本地html资源。同时,WebView也在Android中充当Java代码和JS代码之间交互的桥梁。实际上,也可以将WebView看做一个功能最小化的浏览器。

WebView的应用场景

目前很多公司的 App 使用一个 WebView 作为网页加载, App 中的所有网页内容使用 HTML5 进行展示,这样只需要写一次 HTML5 代码,就可以在 Android 和 iOS 平台上运行,这就是所谓的跨平台 。随着 HTML5 的普及,很多 App 都会内嵌 WebView 来加载 HTML5 页面,即 原生和HTML5 共存,这就是当下最流行的「 混合开发 」。HTML5 最大的优势是迭代方便, 只需要修改服务端的 HTML5 页面,App 会同步更新,无论是做活动推广 App 还是及时修复 Bug 都带来的极大的便利。不过 HTML5 劣势也很明显,当网速不尽如人意时候,加载速度会很慢(不知道5G出现后结果会带来什么变革),也就是HTML5 加载受限于网络,没有原生控件流畅,用户体验相对较差, 所以目前完全使用 HTML5 开发 App 并没有成为主流。

基本使用

先加入权限

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

创建WebView

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

获取WebView实例

//获得控件        WebView webView = (WebView) findViewById(R.id.wv_webview);        //加载网页        webView.loadUrl("http://www.baidu.com");

WebView的状态

mWebView.onResume();// 生命周期onResume    mWebView.resumeTimers();//生命周期resumeTimers    mWebView.onPause();//生命周期onPause    mWebView.pauseTimers();//生命周期pauseTimers (上数四个方法都是成对出现)    mWebView.stopLoading();// 停止当前加载    mWebView.clearMatches();// 清除网页查找的高亮匹配字符。    mWebView.clearHistory();// 清除当前 WebView 访问的历史记录    mWebView.clearSslPreferences();//清除ssl信息    mWebView.clearCache(true);//清空网页访问留下的缓存数据。需要注意的时,由于缓存是全局的,所以只要是WebView用到的缓存都会被清空,即便其他地方也会使用到。该方法接受一个参数,从命名即可看出作用。若设为false,则只清空内存里的资源缓存,而不清空磁盘里的。    mWebView.loadUrl("about:blank");// 清空当前加载    mWebView.removeAllViews();// 清空子 View    mWebView.destroy();// 生命周期销毁

前进、后退网页

Webview.canGoBack();//是否可以后退Webview.goBack();//后退网页Webview.canGoForward();//是否可以前进Webview.goForward();//前进网页Webview.goBackOrForward(intsteps);//以当前的index为起始点前进或者后退到历史记录中指定的steps,如果steps为负数则为后退,正数则为前进

Back键控制网页后退

如果不做任何的处理,触发到Back的时候会直接退出
拦截Back做到后退效果

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

WebView三个重要的部分

1.WebSettings
作用:对WebView进行配置和管理;
2.WebViewClient
作用:处理各种通知 & 请求事件
3.WebChromeClient
作用:辅助 WebView 处理 Javascript 的对话框,网站图标,网站标题等等。

WebSettings类

//声明WebSettings子类WebSettings webSettings = webView.getSettings();//如果访问的页面中要与Javascript交互,则webview必须设置支持JavascriptwebSettings.setJavaScriptEnabled(true);//开启DOM缓存,默认状态下是不支持LocalStorage的webSettings.setDomStorageEnabled(true);//支持插件webSettings.setPluginsEnabled(true); //设置自适应屏幕,两者合用webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小webSettings.setLoadWithOverviewMode(true); // 缩放至屏幕的大小//缩放操作webSettings.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件//缓存//缓存模式如下:    //LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据    //LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。    //LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.    //LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据//不使用缓存webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);//其他细节操作webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //关闭webview中缓存webSettings.setAllowFileAccess(true); //设置可以访问文件webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式

WebViewClient类

1.shouldOverrideUrlLoading()

//处理WebView到底是本身进行处理,还是跳转手机自带的浏览器/*** 1、 默认返回:return super.shouldOverrideUrlLoading(view, url); 这个返回的方法会调用父类方法,也就是跳转至手机浏览器,平时写webview一般都在方法里面写 webView.loadUrl(url);  然后把这个返回值改成下面的false。 * 2、返回: return true;  webview处理url是根据程序来执行的。 * 3、返回: return false; webview处理url是在webview内部执行。 */webView.setWebViewClient(new WebViewClient(){     @Override     public boolean shouldOverrideUrlLoading(WebView view, String url) {           view.loadUrl(url);           return true;      }});

在这个地方还有一个坑给大家说明一下:
1.由于兼容性问题,在Android7.0以上系统访问shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
2.Android7.0以下系统访问shouldOverrideUrlLoading(WebView view, String url)

2.onPageStarted()

//开始载入页面时调用此方法,在这里可以设定一个loading的页面,告诉用户程序正在等待网络响应。webView.setWebViewClient(new WebViewClient(){     @Override      public void onPageStarted(WebView view, String url, Bitmap favicon) {           //设定加载开始的操作     }});

3.onPageFinished()

//在页面加载结束时调用。可以关闭loading 条,切换程序动作。webView.setWebViewClient(new WebViewClient(){     @Override     public void onPageFinished(WebView view, String url) {           //设定加载结束的操作     }});

4.onLoadResource()

//在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次,除非本地有当前 url 对应有缓存,否则就会加载。webView.setWebViewClient(new WebViewClient(){     @Override     public boolean onLoadResource(WebView view, String url) {           //设定加载资源的操作     } });

5.onReceivedError()

//加载页面的服务器出现错误时(如404)调用。// App里面使用webview控件的时候遇到了诸如404这类的错误的时候,若也显示浏览器里面的那种错误提示页面就显得很丑陋了,那么这个时候我们的app就需要加载一个本地的错误提示页面,即webview如何加载一个本地的页面//步骤1:写一个html文件(error_handle.html),用于出错时展示给用户看的提示页面//步骤2:将该html文件放置到代码根目录的assets文件夹下//步骤3:复写WebViewClient的onRecievedError方法 //该方法传回了错误码,根据错误类型可以进行不同的错误分类处理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;           }     }});

6.onReceivedSslError()

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

7.shouldInterceptRequest()这是一个很重要的方法

//WebView拦截请求,重定向/*** 代码中重写了两个shouldInterceptRequest方法* 1.shouldInterceptRequest (WebView view, String url);* 2.shouldInterceptRequest(WebView view, android.webkit.WebResourceRequest request):* 其中shouldInterceptRequest (WebView view, String url)在API 21过时。*/webView.setWebViewClient(new WebViewClient() {     @Override     public void shouldInterceptRequest(WebView view, android.webkit.WebResourceRequest request) {          //WebView中有JS、PNG图片等资源可以截取并更换资源文件      }});

WebChromeClient类

1.onProgressChanged()

//获得网页的加载进度webview.setWebChromeClient(new WebChromeClient(){     @Override     public void onProgressChanged(WebView view, int newProgress) {          // 可以与progressBarView类似的View绑定加载进度});

2.onReceivedTitle()

//接收web页面的 Title。/*** 每个网页的页面都有一个标题,比如www.baidu.com这个页面的标题即“百度一下,你就    知道”,那么如何知道当前webview正在加载的页面的title并进行设置呢?*/webview.setWebChromeClient(new WebChromeClient(){     @Override      public void onReceivedTitle(WebView view, String title) {      titleview.setText(title)}

WebView和JavaScript的交互

1、使用系统方法 addJavascriptInterface 注入 java 对象来实现。
2、利用 WebViewClient 中 shouldOverrideUrlLoading (WebView view, String url) 接口,拦截操作。这个就是很多公司在用的 scheme 方式,通过制定url协议,双方各自解析,使用iframe来调用native代码,实现互通。
3、利用 WebChromeClient 中的 onJsAlert、onJsConfirm、onJsPrompt 提示接口,同样也是拦截操作。

示例代码:

//开启Js可用mWebView.getSettings().setJavaScriptEnabled(true);// 创建要注入的 Java 类public class NativeInterface {    private Context mContext;    public NativeInterface(Context context) {        mContext = context;    }    @JavascriptInterface    public void hello() {        Toast.makeText(mContext, "hello", Toast.LENGTH_SHORT).show();    }    @JavascriptInterface    public void hello(String params) {        Toast.makeText(mContext, params, Toast.LENGTH_SHORT).show();    }    @JavascriptInterface    public String getAndroid() {        Toast.makeText(mContext, "getAndroid", Toast.LENGTH_SHORT).show();        return "Android data";    }}// WebView 注入即可mWebView.addJavascriptInterface(new NativeInterface(this), "AndroidNative");//Js编写<script>    function callHello(){        AndroidNative.hello();    }    function callHello1(){        AndroidNative.hello('hello Android');    }    function callAndroid(){        var temp = AndroidNative.getAndroid();        console.log(temp);        alert(temp);    }  </script>

WebView内存泄漏问题

//mWebView=new WebView(this);mWebView=new WebView(getApplicationContext());LinearLayout linearLayout  = findViewById(R.id.xxx);linearLayout.addView(mWebView);// onDestroy()方法中调用:@Overrideprotected void onDestroy() {    if( mWebView!=null) {       mWebView.setVisibility(View.GONE);       mWebView.removeAllViews();       mWebView.destroy();    }    super.onDestroy();}

感谢大家能够看完本篇文章,如果有说的不正确的地方或者有疑问,可以互相交流。

更多相关文章

  1. [Android] 问题记录 - Cupcake & Donut, Sdcard 正确使用方法
  2. Android手动回收bitmap,引发Canvas: trying to use a recycled b
  3. android实现m3u8直播缓存/下载,M3U8Manger
  4. android支付宝客户端html5网页偶尔无法自动关闭问题
  5. Android启动模式总结
  6. Android动态加载so文件
  7. Android(安卓)中动态加载.jar的实现步骤
  8. Android(安卓)Bitmap 缓存策略
  9. 详解Android(安卓)手机卫士设置向导页面

随机推荐

  1. Study on Android【三】--Intent消息传递
  2. android recovery模式及ROM制作
  3. Android应用程序与SurfaceFlinger服务之
  4. Android(安卓)tools -----Lint
  5. 调试 Android* x86 应用程序的方法以及要
  6. android 面试总结十条
  7. Android高手进阶教程(三)之----Android(
  8. 在Android中调用颜色的方法
  9. adbshell命令详解ZZ
  10. SPDY协议的Android实现 OKHTTP代码分析