Android(安卓)WebView 开发中遇到的那些事儿
前言: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); //在这里可以可以加载进度进度条进度 } });
- 销毁处理
为了避免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使用攻略
- Android成长之路之layout加载过程
- Android异步加载之AsyncTask
- Android(安卓)ImageView的scaleType属性作用
- Mosby -- Android上的MVP框架
- App混合开发之WebView进行H5页面基本操作
- Android(安卓)轻量级缓存框架ASimpleCache分析
- Android(安卓)WebView用法和WebView加载提升网页速度
- 【多媒体编解码】Openmax IL (二)Android多媒体编解码Component架