关于Android中WebView的点滴
2017-06-08 22:34
417 查看
一浏览器缓存机制
移动端 Web 加载性能缓存优化
二配置项列表
WebView的常用方法
WebSettings常用方法
三有些坑
内存泄露的应对
后台无法释放js 导致耗电
onPageFinished是否代表加载完毕
收集链接
在项目中逐步发现对WebView的认知还是不够,基本的用法会,但遇到稍微复杂的bug就摸不着头脑.
在搜集过程中遇到一些总结不错的链接,记录在此, 以备后用:
Web SQL Database 存储机制
Application Cache(AppCache)机制
Indexed Database (IndexedDB)
File System API
通过对一些 H5页面进行调试及抓包发现,每次加载一个 H5页面,都会有较多的请求。除了 HTML 主 URL 自身的请求外,HTML外部引用的 JS、CSS、字体文件、图片都是一个独立的 HTTP 请求,每一个请求都串行的(可能有连接复用)。这么多请求串起来,再加上浏览器解析、渲染的时间,Web 整体的加载时间变得较长;请求文件越多,消耗的流量也会越多。我们可综合使用上面说到几种缓存机制,来帮助我们优化 Web 的加载性能。
结论:综合各种缓存机制比较,对于静态文件,如 JS、CSS、字体、图片等,适合通过浏览器缓存机制来进行缓存,通过缓存文件可大幅提升 Web 的加载速度,且节省流量。但也有一些不足:缓存文件需要首次加载后才会产生;浏览器缓存的存储空间有限,缓存有被清除的可能;缓存的文件没有校验。
对于 Web 在本地或服务器获取的数据,可以通过 Dom Storage 和 IndexedDB 进行缓存。也在一定程度上减少和 Server 的交互,提高加载速度,同时节省流量。
当然 Web 的性能优化,还包括选择合适的图片大小,避免 JS 和 CSS 造成的阻塞等。这就需要 Web 前端的同事根据一些规范和一些调试工具进行优化了。
reload():重新reload当前的URL,即刷新。
boolean canGoBack():用来确认WebView里是否还有可回退的历史记录。通常我们会在WebView里重写返回键的点击事件,通过该方法判断WebView里是否还有历史记录,若有则返回上一页。
boolean canGoForward():用来确认WebView是否还有可向前的历史记录。
boolean canGoBackOrForward(int steps):以当前的页面为起始点,用来确认WebView的历史记录是否足以后退或前进给定的步数,正数为前进,负数为后退。
goBack():在WebView历史记录后退到上一项。
goForward():在WebView历史记录里前进到下一项。
goBackOrForward(int steps):以当前页面为起始点,前进或后退历史记录中指定的步数,正数为前进,负数为后退。
clearCache(boolean includeDiskFiles):清空网页访问留下的缓存数据。需要注意的时,由于缓存是全局的,所以只要是WebView用到的缓存都会被清空,即便其他地方也会使用到。该方法接受一个参数,从命名即可看出作用。若设为false,则只清空内存里的资源缓存,而不清空磁盘里的。
clearHistory():清除当前webview访问的历史记录。
clearFormData():清除自动完成填充的表单数据。需要注意的是,该方法仅仅清除当前表单域自动完成填充的表单数据,并不会清除WebView存储到本地的数据。
onPause():当页面被失去焦点被切换到后台不可见状态,需要执行onPause操作,该操作会通知内核安全地暂停所有动作,比如动画的执行或定位的获取等。需要注意的是该方法并不会暂停JavaScript的执行,若要暂停JavaScript的执行请使用接下来的这个方法。
onResume():在先前调用onPause()后,我们可以调用该方法来恢复WebView的运行。
pauseTimers():该方法面向全局整个应用程序的webview,它会暂停所有webview的layout,parsing,JavaScript Timer。当程序进入后台时,该方法的调用可以降低CPU功耗。
resumeTimers():恢复pauseTimers时的所有操作。
destroy():销毁WebView。需要注意的是:这个方法的调用应在WebView从父容器中被remove掉之后。我们可以手动地调用
rootLayout.removeView(webView);
webView.destroy();
getScrollY():该方法返回的当前可见区域的顶端距整个页面顶端的距离,也就是当前内容滚动的距离。
getHeight():方法都返回当前WebView这个容器的高度。其实以上两个方法都属于View。
getContentHeight():该方法返回整个HTML页面的高度,但该高度值并不等同于当前整个页面的高度,因为WebView有缩放功能, 所以当前整个页面的高度实际上应该是原始HTML的高度再乘上缩放比例。因此,准确的判断方法应该是
if (webView.getContentHeight() * webView.getScale() == (webView.getHeight() + webView.getScrollY())) {
//已经处于底端
}
if(webView.getScrollY() == 0){
//处于顶端
}
pageUp(boolean top):将WebView展示的页面滑动至顶部。
pageDown(boolean bottom):将WebView展示的页面滑动至底部。
setJavaScriptCanOpenWindowsAutomatically(boolean flag):设置WebView是否可以由JavaScript自动打开窗口,默认为false,通常与JavaScript的window.open()配合使用。
setAllowFileAccess(boolean allow):启用或禁用WebView访问文件数据。
setBlockNetworkImage(boolean flag):禁止或允许WebView从网络上加载图片。需要注意的是,如果设置是从禁止到允许的转变的话,图片数据并不会在设置改变后立刻去获取,而是在WebView调用reload()的时候才会生效。
这个时候,需要确保这个app拥有访问Internet的权限,否则会抛出安全异常。
通常没有禁止图片加载的需求的时候,完全不用管这个方法,因为当我们的app拥有访问Internet的权限时,这个flag的默认值就是false。
setSupportZoom(boolean support):设置是否支持缩放。
setBuiltInZoomControls(boolean enabled):显示或不显示缩放按钮(wap网页不支持)。
setSupportMultipleWindows(boolean support):设置WebView是否支持多窗口。
setLayoutAlgorithm(WebSettings.LayoutAlgorithm l):指定WebView的页面布局显示形式,调用该方法会引起页面重绘。默认值为LayoutAlgorithm#NARROW_COLUMNS。
setNeedInitialFocus(boolean flag):通知WebView是否需要设置一个节点获取焦点当WebView#requestFocus(int,android.graphics.Rect)被调用时,默认为true。
setAppCacheEnabled(boolean flag):启用或禁用应用缓存。
setAppCachePath(String appCachePath):设置应用缓存路径,这个路径必须是可以让app写入文件的。该方法应该只被调用一次,重复调用会被无视~
setCacheMode(int mode):用来设置WebView的缓存模式。当我们加载页面或从上一个页面返回的时候,会按照设置的缓存模式去检查并使用(或不使用)缓存。
缓存模式有四种:
LOAD_DEFAULT:默认的缓存使用模式。在进行页面前进或后退的操作时,如果缓存可用并未过期就优先加载缓存,否则从网络上加载数据。这样可以减少页面的网络请求次数。
LOAD_CACHE_ELSE_NETWORK:只要缓存可用就加载缓存,哪怕它们已经过期失效。如果缓存不可用就从网络上加载数据。
LOAD_NO_CACHE:不加载缓存,只从网络加载数据。
LOAD_CACHE_ONLY:不从网络加载数据,只从缓存加载数据。
通常我们可以根据网络情况将这几种模式结合使用,比如有网的时候使用LOAD_DEFAULT,离线时使用LOAD_CACHE_ONLY、LOAD_CACHE_ELSE_NETWORK,让用户不至于在离线时啥都看不到。
setDatabaseEnabled(boolean flag):启用或禁用数据库缓存。
setDomStorageEnabled(boolean flag):启用或禁用DOM缓存。
setUserAgentString(String ua):设置WebView的UserAgent值。
setDefaultEncodingName(String encoding):设置编码格式,通常都设为“UTF-8”。
setStandardFontFamily(String font):设置标准的字体族,默认“sans-serif”。
setCursiveFontFamily:设置草书字体族,默认“cursive”。
setFantasyFontFamily:设置CursiveFont字体族,默认“cursive”。
setFixedFontFamily:设置混合字体族,默认“monospace”。
setSansSerifFontFamily:设置梵文字体族,默认“sans-serif”。
setSerifFontFamily:设置衬线字体族,默认“sans-serif”
setDefaultFixedFontSize(int size):设置默认填充字体大小,默认16,取值区间为[1-72],超过范围,使用其上限值。
setDefaultFontSize(int size):设置默认字体大小,默认16,取值区间[1-72],超过范围,使用其上限值。
setMinimumFontSize:设置最小字体,默认8. 取值区间[1-72],超过范围,使用其上限值。
setMinimumLogicalFontSize:设置最小逻辑字体,默认8. 取值区间[1-72],超过范围,使用其上限值。
这是目前对于webview 内存泄露 最好的解决方案。使用此方法 所有因为webview引发的 资源无法释放等问题 全部可以解决。
2.如果实在不想用开额外进程的方式解决webview 内存泄露的问题,那么下面的方法很大程度上可以避免这种情况; 在webview的 destroy方法里 调用这个方法就行(注:未经验证,有待考究原因)。
这些资源是不会被释放,用户也无法感知,导致一直占有cpu 耗电特别快,所以大家记住了,如果遇到这种情况 请在onstop和onresume里分别把setJavaScriptEnabled();
给设置成false和true。
BUT,甚至于onProgressChanged这个函数都比onPageFinished 要准一些。有空的同学可以跟一下源码,onPageFinished 在不同的内核里 调用的时机都不一样。
史上最全webview详解,2016-04-07
WebView·开车指南,2016-08-31
WebView你真的熟悉吗?from 简书 2016.08.18
WebView加载速度优化(离线缓存和预加载),2016.05.25
移动端 Web 加载性能缓存优化
二配置项列表
WebView的常用方法
WebSettings常用方法
三有些坑
内存泄露的应对
后台无法释放js 导致耗电
onPageFinished是否代表加载完毕
收集链接
在项目中逐步发现对WebView的认知还是不够,基本的用法会,但遇到稍微复杂的bug就摸不着头脑.
在搜集过程中遇到一些总结不错的链接,记录在此, 以备后用:
一.浏览器缓存机制
Dom Storgage(Web Storage)存储机制Web SQL Database 存储机制
Application Cache(AppCache)机制
Indexed Database (IndexedDB)
File System API
移动端 Web 加载性能(缓存)优化
分析完 H5提供的各种缓存机制,回到移动端(针对 Android,可能也适用于 iOS)的场景。现在 Android App 大多嵌入了 Webview 的组件,通过内嵌 Webview 来加载一些H5的运营活动页面或资讯页。这样可充分发挥Web前端的优势:快速开发、发布,灵活上下线。但 Webview 也有一些不可忽视的问题,比较突出的就是加载相对较慢,会相对消耗较多流量。通过对一些 H5页面进行调试及抓包发现,每次加载一个 H5页面,都会有较多的请求。除了 HTML 主 URL 自身的请求外,HTML外部引用的 JS、CSS、字体文件、图片都是一个独立的 HTTP 请求,每一个请求都串行的(可能有连接复用)。这么多请求串起来,再加上浏览器解析、渲染的时间,Web 整体的加载时间变得较长;请求文件越多,消耗的流量也会越多。我们可综合使用上面说到几种缓存机制,来帮助我们优化 Web 的加载性能。
结论:综合各种缓存机制比较,对于静态文件,如 JS、CSS、字体、图片等,适合通过浏览器缓存机制来进行缓存,通过缓存文件可大幅提升 Web 的加载速度,且节省流量。但也有一些不足:缓存文件需要首次加载后才会产生;浏览器缓存的存储空间有限,缓存有被清除的可能;缓存的文件没有校验。
对于 Web 在本地或服务器获取的数据,可以通过 Dom Storage 和 IndexedDB 进行缓存。也在一定程度上减少和 Server 的交互,提高加载速度,同时节省流量。
当然 Web 的性能优化,还包括选择合适的图片大小,避免 JS 和 CSS 造成的阻塞等。这就需要 Web 前端的同事根据一些规范和一些调试工具进行优化了。
二.配置项列表
WebView的常用方法
String getUrl():获取当前页面的URL。reload():重新reload当前的URL,即刷新。
boolean canGoBack():用来确认WebView里是否还有可回退的历史记录。通常我们会在WebView里重写返回键的点击事件,通过该方法判断WebView里是否还有历史记录,若有则返回上一页。
boolean canGoForward():用来确认WebView是否还有可向前的历史记录。
boolean canGoBackOrForward(int steps):以当前的页面为起始点,用来确认WebView的历史记录是否足以后退或前进给定的步数,正数为前进,负数为后退。
goBack():在WebView历史记录后退到上一项。
goForward():在WebView历史记录里前进到下一项。
goBackOrForward(int steps):以当前页面为起始点,前进或后退历史记录中指定的步数,正数为前进,负数为后退。
clearCache(boolean includeDiskFiles):清空网页访问留下的缓存数据。需要注意的时,由于缓存是全局的,所以只要是WebView用到的缓存都会被清空,即便其他地方也会使用到。该方法接受一个参数,从命名即可看出作用。若设为false,则只清空内存里的资源缓存,而不清空磁盘里的。
clearHistory():清除当前webview访问的历史记录。
clearFormData():清除自动完成填充的表单数据。需要注意的是,该方法仅仅清除当前表单域自动完成填充的表单数据,并不会清除WebView存储到本地的数据。
onPause():当页面被失去焦点被切换到后台不可见状态,需要执行onPause操作,该操作会通知内核安全地暂停所有动作,比如动画的执行或定位的获取等。需要注意的是该方法并不会暂停JavaScript的执行,若要暂停JavaScript的执行请使用接下来的这个方法。
onResume():在先前调用onPause()后,我们可以调用该方法来恢复WebView的运行。
pauseTimers():该方法面向全局整个应用程序的webview,它会暂停所有webview的layout,parsing,JavaScript Timer。当程序进入后台时,该方法的调用可以降低CPU功耗。
resumeTimers():恢复pauseTimers时的所有操作。
destroy():销毁WebView。需要注意的是:这个方法的调用应在WebView从父容器中被remove掉之后。我们可以手动地调用
rootLayout.removeView(webView);
webView.destroy();
getScrollY():该方法返回的当前可见区域的顶端距整个页面顶端的距离,也就是当前内容滚动的距离。
getHeight():方法都返回当前WebView这个容器的高度。其实以上两个方法都属于View。
getContentHeight():该方法返回整个HTML页面的高度,但该高度值并不等同于当前整个页面的高度,因为WebView有缩放功能, 所以当前整个页面的高度实际上应该是原始HTML的高度再乘上缩放比例。因此,准确的判断方法应该是
if (webView.getContentHeight() * webView.getScale() == (webView.getHeight() + webView.getScrollY())) {
//已经处于底端
}
if(webView.getScrollY() == 0){
//处于顶端
}
pageUp(boolean top):将WebView展示的页面滑动至顶部。
pageDown(boolean bottom):将WebView展示的页面滑动至底部。
WebSettings常用方法
setJavaScriptEnabled(boolean flag):设置WebView是否可以运行JavaScript。setJavaScriptCanOpenWindowsAutomatically(boolean flag):设置WebView是否可以由JavaScript自动打开窗口,默认为false,通常与JavaScript的window.open()配合使用。
setAllowFileAccess(boolean allow):启用或禁用WebView访问文件数据。
setBlockNetworkImage(boolean flag):禁止或允许WebView从网络上加载图片。需要注意的是,如果设置是从禁止到允许的转变的话,图片数据并不会在设置改变后立刻去获取,而是在WebView调用reload()的时候才会生效。
这个时候,需要确保这个app拥有访问Internet的权限,否则会抛出安全异常。
通常没有禁止图片加载的需求的时候,完全不用管这个方法,因为当我们的app拥有访问Internet的权限时,这个flag的默认值就是false。
setSupportZoom(boolean support):设置是否支持缩放。
setBuiltInZoomControls(boolean enabled):显示或不显示缩放按钮(wap网页不支持)。
setSupportMultipleWindows(boolean support):设置WebView是否支持多窗口。
setLayoutAlgorithm(WebSettings.LayoutAlgorithm l):指定WebView的页面布局显示形式,调用该方法会引起页面重绘。默认值为LayoutAlgorithm#NARROW_COLUMNS。
setNeedInitialFocus(boolean flag):通知WebView是否需要设置一个节点获取焦点当WebView#requestFocus(int,android.graphics.Rect)被调用时,默认为true。
setAppCacheEnabled(boolean flag):启用或禁用应用缓存。
setAppCachePath(String appCachePath):设置应用缓存路径,这个路径必须是可以让app写入文件的。该方法应该只被调用一次,重复调用会被无视~
setCacheMode(int mode):用来设置WebView的缓存模式。当我们加载页面或从上一个页面返回的时候,会按照设置的缓存模式去检查并使用(或不使用)缓存。
缓存模式有四种:
LOAD_DEFAULT:默认的缓存使用模式。在进行页面前进或后退的操作时,如果缓存可用并未过期就优先加载缓存,否则从网络上加载数据。这样可以减少页面的网络请求次数。
LOAD_CACHE_ELSE_NETWORK:只要缓存可用就加载缓存,哪怕它们已经过期失效。如果缓存不可用就从网络上加载数据。
LOAD_NO_CACHE:不加载缓存,只从网络加载数据。
LOAD_CACHE_ONLY:不从网络加载数据,只从缓存加载数据。
通常我们可以根据网络情况将这几种模式结合使用,比如有网的时候使用LOAD_DEFAULT,离线时使用LOAD_CACHE_ONLY、LOAD_CACHE_ELSE_NETWORK,让用户不至于在离线时啥都看不到。
setDatabaseEnabled(boolean flag):启用或禁用数据库缓存。
setDomStorageEnabled(boolean flag):启用或禁用DOM缓存。
setUserAgentString(String ua):设置WebView的UserAgent值。
setDefaultEncodingName(String encoding):设置编码格式,通常都设为“UTF-8”。
setStandardFontFamily(String font):设置标准的字体族,默认“sans-serif”。
setCursiveFontFamily:设置草书字体族,默认“cursive”。
setFantasyFontFamily:设置CursiveFont字体族,默认“cursive”。
setFixedFontFamily:设置混合字体族,默认“monospace”。
setSansSerifFontFamily:设置梵文字体族,默认“sans-serif”。
setSerifFontFamily:设置衬线字体族,默认“sans-serif”
setDefaultFixedFontSize(int size):设置默认填充字体大小,默认16,取值区间为[1-72],超过范围,使用其上限值。
setDefaultFontSize(int size):设置默认字体大小,默认16,取值区间[1-72],超过范围,使用其上限值。
setMinimumFontSize:设置最小字体,默认8. 取值区间[1-72],超过范围,使用其上限值。
setMinimumLogicalFontSize:设置最小逻辑字体,默认8. 取值区间[1-72],超过范围,使用其上限值。
三.有些坑
内存泄露的应对
1.你要用webview的时候,最好 另外单独开一个进程 去使用webview 并且当这个 进程结束时,请手动调用System.exit(0)。这是目前对于webview 内存泄露 最好的解决方案。使用此方法 所有因为webview引发的 资源无法释放等问题 全部可以解决。
2.如果实在不想用开额外进程的方式解决webview 内存泄露的问题,那么下面的方法很大程度上可以避免这种情况; 在webview的 destroy方法里 调用这个方法就行(注:未经验证,有待考究原因)。
public void releaseAllWebViewCallback() { if (android.os.Build.VERSION.SDK_INT < 16) { try { Field field = WebView.class.getDeclaredField("mWebViewCore"); field = field.getType().getDeclaredField("mBrowserFrame"); field = field.getType().getDeclaredField("sConfigCallback"); field.setAccessible(true); field.set(null, null); } catch (NoSuchFieldException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); } } catch (IllegalAccessException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); } } } else { try { Field sConfigCallback = Class.forName("android.webkit.BrowserFrame").getDeclaredField("sConfigCallback"); if (sConfigCallback != null) { sConfigCallback.setAccessible(true); sConfigCallback.set(null, null); } } catch (NoSuchFieldException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); } } catch (ClassNotFoundException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); } } catch (IllegalAccessException e) { if (BuildConfig.DEBUG) { e.printStackTrace(); } } } }
后台无法释放js 导致耗电
如果webview加载的html里 有一些js 一直在执行比如动画之类的东西,如果此刻webview 挂在了后台这些资源是不会被释放,用户也无法感知,导致一直占有cpu 耗电特别快,所以大家记住了,如果遇到这种情况 请在onstop和onresume里分别把setJavaScriptEnabled();
给设置成false和true。
onPageFinished是否代表加载完毕
多数开发者都是参考的http://stackoverflow.com/questions/3149216/how-to-listen-for-a-webview-finishing-loading-a-url-in-android 这个上面的高票答案。BUT,甚至于onProgressChanged这个函数都比onPageFinished 要准一些。有空的同学可以跟一下源码,onPageFinished 在不同的内核里 调用的时机都不一样。
收集链接:
(重要!)H5 缓存机制浅析 移动端 Web 加载性能优化,bugly,2017.5.15史上最全webview详解,2016-04-07
WebView·开车指南,2016-08-31
WebView你真的熟悉吗?from 简书 2016.08.18
WebView加载速度优化(离线缓存和预加载),2016.05.25
相关文章推荐
- 关于android WebViewClient 的方法解释
- Android 关于WebView的相关属性
- 关于android webview中访问web页面带有upload上传控件的解决办法
- 关于Android WebView的那点事儿..
- 关于Android WebView内容不同屏幕兼容处理
- android 4.0中关于webview加载flash并使flash全屏的问题(附demo)
- [Android] 关于WebView的内存泄露问题
- Android中关于WebView的使用办法
- android 关于webview的小小总结
- 关于Android webView的用法
- 关于android WebViewClient和WebChromeClient
- 关于android webview读取js全局变量或者函数返回值
- 关于android 端,人人网以及新浪网 webview 页面缓存问题
- 关于android WebViewClient的方法解释
- 关于android的WebView
- [Android实例] 关于webview如何自动登录保存登录信息
- 关于android WebViewClient的方法解释
- 关于android WebViewClient的方法解释
- 关于android WebViewClient的方法解释
- android 4.0中关于webview加载flash并使flash全屏的问题(附demo)