前言: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详尽介绍
网友评论