美文网首页
Android WebView 开发中遇到的那些事儿

Android WebView 开发中遇到的那些事儿

作者: A挑战未来A | 来源:发表于2018-05-23 18:59 被阅读0次

前言:WebView是Android里比较特殊的一个控件,是Android混合开发(原生开发+web开发)的基础。笔者目前开发的项目,用到WebView地方还是比较多的,遇到了不少坑,为了避免遇到类似的问题,今天在这里针对webView做一篇系统的归纳总结,希望对别人能有帮助。
WebView是基于webkit引擎、展现web页面的控件,在低版本和高版本采用了不同的webkit版本内核,4.4后直接使用了Chrome。可以用于显示和渲染Web页面,直接展示Html文件(网络或者本地文件),可以和JavaScript交互。

1. webView基本使用;

WebView webView= (WebView) findViewById(R.id.webView);
String url="http://go.10086.cn/rd/go/dh/";
webView.loadUrl(url);

这种基本使用可以实现webView加载网页或者本地Html文件,但是存在一个问题,当在网页中点击进入下一个网页的时候,会自定跳转到手机系统浏览器中加载的,这种用户体验往往是非常不友好的,无论加载多少网页,始终在自己开发的app内,才是一个有逼格(文字捂脸)的开发人员,应该实现的,代码修改为:

WebView webView= (WebView) findViewById(R.id.webView);
        String url="http://go.10086.cn/rd/go/dh/";
        webView.loadUrl(url);
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
//                return false;//这里笔者测试的时候,返回false和true效果是一样的
                //所有网页都是在程序中进行加载的TODO
                return true;
            }
        });

如果没有什么特殊要求,基本上上面代码就可以实现我们日常加载网页的基本需求。但是我们混合开发往往没有那么简单,或者需要在网页中录入信息,加载图片,如果js中有缓存问题,Android端没有进行相应的设置,会出现很多问题,下面是一些常用设置,后面都有详细说明。

2. webView 常用设置项;

WebSettings ws = webView.getSettings();
        //以下两条共同设置网页适应手机屏幕
        ws.setUseWideViewPort(true);//设置网页图片适用手机屏幕,适应webView;
        ws.setLoadWithOverviewMode(true);//设置网络缩小至屏幕大小
        // 设置此属性,可任意比例缩放。
        ws.setUseWideViewPort(true);
        // 缩放比例 1
        webView.setInitialScale(100);

        //设置字符
        ws.setDefaultTextEncodingName("utf-8");
        //缩放操作
        ws.setSupportZoom(true); //支持缩放,默认为true。是下面那个的前提。
        ws.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
        ws.setDisplayZoomControls(false); //隐藏原生的缩放控件
        // 启动应用缓存
        ws.setAppCacheEnabled(true);
        ws.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);

        //其他细节操作#########################
        //缓存模式如下:
        //LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
        //LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
        //LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
        //LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。(没有网络则从本地获取)
        ws.setCacheMode(WebSettings.LOAD_NO_CACHE); //关闭webview中缓存(不使用本地缓存,否则部分弹窗不消失)
        // 使用localStorage则必须打开&&&&&&&这个必须加上
        /**
         * 这个属性不添加遇到的坑:
         * 坑1:如果js那边添加本地缓存,没有设置这个属性,会导致js代码执行出现异常
         * 坑2:没有下面这条,h5中使用的css标签实现的弹窗功能异常,不消失一直旋转,加上之后正常(感觉是不是也是因为js那边加了缓存)
         */
        ws.setDomStorageEnabled(true);
        // setDefaultZoom  api19被弃用
        // 告诉WebView启用JavaScript执行。默认的是false。
        ws.setJavaScriptEnabled(true);
        //  页面加载好以后,再放开图片  这个建议设置为false,如果设置为true,图片容易加载不出来
        ws.setBlockNetworkImage(false);
//         排版适应屏幕
        ws.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
        // WebView是否支持多个窗口。
        ws.setSupportMultipleWindows(true);
        // webview从5.0开始默认不允许混合模式,https中不能加载http资源,需要设置开启。
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            ws.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }
        //设置字体默认缩放大小(改变网页字体大小,setTextSize  api14被弃用)
        //值为100的时候正常
        ws.setTextZoom(100);

上面是关于WebView一些常用的设置,可以参考自己的需求进行设置,笔者建议全部加上,反正复制粘贴的问题,避免以后使用出现各种意外情况,特别缓存那块。

3. 深入使用

3.1 Js调用Android代码
Android 端部分代码实现如下:

  `````
private void loadUrl(String url) {
    if (TextUtils.isEmpty(url)) {
        ToastUtils.makeLongText(this, "开户路径是空");
        return;
    }
    //开启JavaScript支持
    WebSettings webSettings = webView.getSettings();

    webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
    webSettings.setUseWideViewPort(true);//设置webview推荐使用的窗口
    webSettings.setLoadWithOverviewMode(true);//设置webview加载的页面的模式
    webSettings.setDisplayZoomControls(false);//隐藏webview缩放按钮
    webSettings.setJavaScriptEnabled(true); // 设置支持javascript脚本
    webSettings.setAllowFileAccess(true); // 允许访问文件
    webSettings.setBuiltInZoomControls(true); // 设置显示缩放按钮
    webSettings.setSupportZoom(true); // 支持缩放
    //没有下面这条,h5中使用的css标签功能异常,加上之后正常  #########################
    webSettings.setDomStorageEnabled(true);//解决部分标签不支持的问题
    //LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
    //LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
    //LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
    //LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。(没有网络则从本地获取)
    webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); //关闭webview中缓存(不使用本地缓存,否则部分弹窗不消失)
    webView.getSettings().setJavaScriptEnabled(true);

    //放在assets的html需加上android_asset/  也可以用网络上的文件
    webView.setWebViewClient(new WebViewClient() {
        //覆盖shouldOverrideUrlLoading 方法
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    });
    webView.loadUrl(url);
   // 添加一个对象, 让JS可以访问该对象的方法, 该对象中可以调用JS中的方法
    webView.addJavascriptInterface(new JSInterface1(), "android");

}

  `````
 ``````
  class JSInterface1 {
    //JavaScript调用此方法
  //笔者测试发现,该方法在非主线程中执行如果在方法中,直接修改Ui,系统会抛出异常;(汗颜,道行尚欠)
    @JavascriptInterface
    public void back() {
   //mHandler在主线程中创建对象
       mHandler.post(new Runnable() {
            @Override
            public void run() {
                EventBus.getDefault().post(new EventBusPersonInfoList("123"));
                finish();
            }
        });
    }
}

3.2 Android调用js代码
这个部分目前笔者项目中还没有涉及到过,曾将尝试写个demo测试一下,由于前端代码不是很精通,没有实现,所以这里就不过多贴代码了,后面项目中用到之后,立即补充。
3.3 webView加载网页进度条实现
笔者目前通过学习webView相关知识了解到,webView加载进度条的实现方式有两种:
方式一:旋转的进度实现,页面加载开始弹出,页面渲染完毕后消失,实现方式如下

webView.setWebViewClient(new WebViewClient() {
                @Override
                public void onPageStarted(WebView view, String url, Bitmap favicon) {
                    super.onPageStarted(view, url, favicon);
                    showWaitDialog();
                }

                @Override
                public void onPageFinished(WebView view, String url) {
                    super.onPageFinished(view, url);
                    dismissDialog();
                }
                //覆盖shouldOverrideUrlLoading 方法

                @Override
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    view.loadUrl(url);
                    return false;
                }
            });

方式二:类似网页加载中,页面加载上面有个横向的进度条,根据网络渲染进度,加载进度条进度

webview.setWebChromeClient(new WebChromeClient(){
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
                //在这里可以可以加载进度进度条进度
            }
        });
  1. 销毁处理
    为了避免webView造成内存卸载,需要在页面销毁的同时销毁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();
    }

总结

写这篇文章的过程中,其实是一个知识总结记录,内心反思的过程,老实说,写这篇文章的时候,笔者内心是比较心虚的,为啥呢,说实话,我看过很多前辈写的关于WebView相关的文章,写得非常好,非常深入,文章中,既说明了怎么做,还说明了为啥这么做,对比自己写的这边文章,感觉自己太low了,但是思前想后,还是要写这篇文章,万事开头难,越不写,越不敢写,越不会写,所以一定要写,只有写才会有提高。
最后关于这篇文章,无论知识的广度还是深度,都是比较皮毛的,这篇文章重点是记录自己工作中遇到的问题,能够帮助其他,笔者非常感到荣幸,但愿不会误人子弟(捂脸),文章有任何不对不足的地方,欢迎各位留言斧正,谢谢!
下面是自己学习webView相关文章,仅供参考:
关于webView常见Api最详尽介绍
关于webView和android互相调用
关于webView使用漏洞
关于webView详尽介绍

相关文章

网友评论

      本文标题:Android WebView 开发中遇到的那些事儿

      本文链接:https://www.haomeiwen.com/subject/ifkrjftx.html