关于Android中WebView的点滴

在项目中逐步发现对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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值