android webView的缓存机制和资源预加载

android 原生使用WebView嵌入H5页面 Hybrid开发

一、性能问题

  • android webview 里H5加载速度慢
  • 网络流量大
1、H5页面加载速度慢
  1. 渲染速度慢

    js解析效率

    js本身的解析过程复杂、解析速度不快,前端页面设计较多的js代码文件

    手机硬件设备的性能

    机型多,硬件性能不一

  2. 资源加载慢

    H5页面的资源多

    网络请求数量多

    ​ H5页面所有资源都需要从网络请求

二、解决方案

  • webView组件本身的缓存机制
  • 资源预加载
  • 资源拦截

webView组件本身的缓存机制

  • WebView自带的缓存机制有5种:浏览器 缓存机制

  • Application Cache 缓存机制

  • Dom Storage 缓存机制

  • Web SQL Database 缓存机制

  • Indexed Database 缓存机制

  • File System 缓存机制(H5页面新加入的缓存机制,虽然Android WebView暂时不支持,但会进行简单介绍)

    (1) Cache-Control: 用于控制文件在本地缓存的有效时长

    ​ eg:Cache-Control:max-age=600,则表示文件在本地应该缓存,且有效时长是600秒(从发出请求算起)。在接下来600秒内,如果有请求这个资源,浏览器不会发出 HTTP 请求,而是直接使用本地缓存的文件。

    (2)Expires: 与Cache-Control 功能相同,即控制缓存的有效时间

    ​ cache-Control 优先级高

    (3) Last-Modified: 标识文件在服务器上的最新更新时间

    ​ 下次请求时,如果文件缓存过期,浏览器通过 If-Modified-Since 字段带上这个时间,发送给服务器,由服务器比较时间戳来判断文件是否有修改。如果没有修改,服务器返回304告诉浏览器继续使用缓存;如果有修改,则返回200,同时返回最新的文件。

    (4) Etag:功能同Last-Modified, 即标识文件在服务器上的最新更新时间

优点:支持Http协议层

缺点:缓存文件需要首次加载后才会产生;浏览器缓存的存储空间有限,缓存有被清楚的可能,缓存的文件没有校验

可以缓存讲台文件资源,如JS,CSS、文本、图片等,webView 会将缓存的文件记录及文件内容会存在当前appde data目录中,

Application Cache 缓存机制

以文件为单位进行缓存,且文件有一定更新机制(类似于浏览器缓存机制)

AppCache : manifest 属性和manifest文件

<!DOCTYPE html>
<html manifest="demo_html.appcache">
// HTML 在头中通过 manifest 属性引用 manifest 文件
// manifest 文件:就是上面以 appcache 结尾的文件,是一个普通文件文件,列出了需要缓存的文件
// 浏览器在首次加载 HTML 文件时,会解析 manifest 属性,并读取 manifest 文件,获取 Section:CACHE MANIFEST 下要缓存的文件列表,再对文件缓存
<body>
...
</body>
</html>

// 原理说明如下:
AppCache 在首次加载生成后,也有更新机制。被缓存的文件如果要更新,需要更新 manifest 文件
因为浏览器在下次加载时,除了会默认使用缓存外,还会在后台检查 manifest 文件有没有修改(byte by byte)
发现有修改,就会重新获取 manifest 文件,对 Section:CACHE MANIFEST 下文件列表检查更新
manifest 文件与缓存文件的检查更新也遵守浏览器缓存机制
如用户手动清了 AppCache 缓存,下次加载时,浏览器会重新生成缓存,也可算是一种缓存的更新
AppCache 的缓存文件,与浏览器的缓存文件分开存储的,因为 AppCache 在本地有 5MB(分 HOST)的空间限制

    // 通过设置WebView的settings来实现WebSettings settings = getSettings();String cacheDirPath = context.getFilesDir().getAbsolutePath()+"cache/";settings.setAppCachePath(cacheDirPath);// 1. 设置缓存路径settings.setAppCacheMaxSize(20*1024*1024);// 2. 设置缓存大小settings.setAppCacheEnabled(true);// 3. 开启Application Cache存储机制

Application 只调用一次 WebSettings.setAppCachePath() 和
WebSettings.setAppCacheMaxSize()

Dom Storage 缓存机制

通过存储字符串的Key-Value 对来提供

sessionStorage:具备临时性,即存储与页面相关的数据,它在页面关闭后无法使用
localStorage:具备持久性,即保存的数据在页面关闭后也可以使用。

特点:

  • 存储空间大(5MB): 存储空间对于不同浏览器不同,如Cookies才4KB
  • 存储安全、便捷:Dom Storage 存储的数据在本地,不需要经常和服务器进行交互。

应用:

​ 存储临时、简单的数据

​ 类似于sharedPreference机制

    // 通过设置 `WebView`的`Settings`类实现WebSettings settings = getSettings();settings.setDomStorageEnabled(true);// 开启DOM storage

Web SQL Database 缓存机制

​ 基于SQL的数据库存储机制

​ 充分利用数据库的优势,可方便对数据进行增加、删除、修改、查询。

应用:

​ 存储适合数据库的结构化数据

    // 通过设置WebView的settings实现WebSettings settings = getSettings();String cacheDirPath = context.getFilesDir().getAbsolutePath()+"cache/";settings.setDatabasePath(cacheDirPath);// 设置缓存路径settings.setDatabaseEnabled(true);// 开启 数据库存储机制

官方说明,Web SQL Database 存储机制不在推荐使用(不在维护),取而代之的是IndexedDB缓存机制。

IndexedDB缓存机制

属于NoSQL数据库,通过存储字符串的Key-Value对来提供,类似于Dom Storage 存储机制的key-value存储方式

优点:

  • 功能强大、使用简单

    通过数据库的事务(tranction)机制进行数据操作

    可对对象任何属性生成索引,方便查询

  • 存储空间大

    较大的存储空间,默认推荐250MB(分HOST)

  • 使用灵活

    以key-value的方式存存取对象,可以是任何类型值或对象,包括二级制

    异步的API调用,避免造成等待而影响体验

存储 复杂、数据量大的结构化数据

// 通过设置WebView的settings实现
WebSettings settings = getSettings();

    settings.setJavaScriptEnabled(true);// 只需设置支持JS就自动打开IndexedDB存储机制// Android 在4.4开始加入对 IndexedDB 的支持,只需打开允许 JS 执行的开关就好了。

资源预加载

​ 提前加载将使用的H5页面,即提前构建缓存

​ 预加载webView 、预加载H5资源

预加载WebView对象

​ 提前初始化一个webView对象,后续复用这个webView对象

预加载H5资源

  1. 在应用启动、初始化第一个WebView对象时,直接开始网络请求加载H5页面
  2. 后续需打开这些H5页面时就直接从该本地对象中获取

自身构建缓存

为了有效解决 Android WebView 的性能问题,除了使用 Android WebView 自身的缓存机制,还可以自己针对某一需求场景构建缓存机制。

实现方法:

  1. 事先将更新频率较低、常用 & 固定的H5静态资源 文件(如JSCSS文件、图片等) 放到本地
  2. 拦截H5页面的资源网络请求 并进行检测
  3. 如果检测到本地具有相同的静态资源 就 直接从本地读取进行替换 而 不发送该资源的网络请求 到 服务器获取

实现方法:

假设现在需要拦截一个图片的资源并用本地资源进行替代

    mWebview.setWebViewClient(new WebViewClient() {// 重写 WebViewClient  的  shouldInterceptRequest ()// API 21 以下用shouldInterceptRequest(WebView view, String url)// API 21 以上用shouldInterceptRequest(WebView view, WebResourceRequest request)// 下面会详细说明// API 21 以下用shouldInterceptRequest(WebView view, String url)@Overridepublic WebResourceResponse shouldInterceptRequest(WebView view, String url) {// 步骤1:判断拦截资源的条件,即判断url里的图片资源的文件名if (url.contains("logo.gif")) {// 假设网页里该图片资源的地址为:http://abc.com/imgage/logo.gif// 图片的资源文件名为:logo.gifInputStream is = null;// 步骤2:创建一个输入流try {is =getApplicationContext().getAssets().open("images/abc.png");// 步骤3:获得需要替换的资源(存放在assets文件夹里)// a. 先在app/src/main下创建一个assets文件夹// b. 在assets文件夹里再创建一个images文件夹// c. 在images文件夹放上需要替换的资源(此处替换的是abc.png图片)} catch (IOException e) {e.printStackTrace();}// 步骤4:替换资源WebResourceResponse response = new WebResourceResponse("image/png","utf-8", is);// 参数1:http请求里该图片的Content-Type,此处图片为image/png// 参数2:编码类型// 参数3:存放着替换资源的输入流(上面创建的那个)return response;}return super.shouldInterceptRequest(view, url);}

       // API 21 以上用shouldInterceptRequest(WebView view, WebResourceRequest request)@TargetApi(Build.VERSION_CODES.LOLLIPOP)@Overridepublic WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {// 步骤1:判断拦截资源的条件,即判断url里的图片资源的文件名if (request.getUrl().toString().contains("logo.gif")) {// 假设网页里该图片资源的地址为:http://abc.com/imgage/logo.gif// 图片的资源文件名为:logo.gifInputStream is = null;// 步骤2:创建一个输入流try {is = getApplicationContext().getAssets().open("images/abc.png");// 步骤3:获得需要替换的资源(存放在assets文件夹里)// a. 先在app/src/main下创建一个assets文件夹// b. 在assets文件夹里再创建一个images文件夹// c. 在images文件夹放上需要替换的资源(此处替换的是abc.png图片} catch (IOException e) {e.printStackTrace();}// 步骤4:替换资源WebResourceResponse response = new WebResourceResponse("image/png","utf-8", is);// 参数1:http请求里该图片的Content-Type,此处图片为image/png// 参数2:编码类型// 参数3:存放着替换资源的输入流(上面创建的那个)return response;}return super.shouldInterceptRequest(view, request);}
});
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/388899.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql springboot 缓存_Spring Boot 整合 Redis 实现缓存操作

摘要: 原创出处 www.bysocket.com 「泥瓦匠BYSocket 」欢迎转载&#xff0c;保留摘要&#xff0c;谢谢&#xff01;『 产品没有价值&#xff0c;开发团队再优秀也无济于事 – 《启示录》 』本文提纲一、缓存的应用场景二、更新缓存的策略三、运行 springboot-mybatis-redis 工程…

http压力测试工具及使用说明

http压力测试工具及使用说明 转 说明&#xff1a;介绍几款简单、易使用http压测工具&#xff0c;便于研发同学&#xff0c;压测服务&#xff0c;明确服务临界值&#xff0c;寻找服务瓶颈点。 压测时候可重点以下指标&#xff0c;关注并发用户数、TPS&#xff08;每秒事务数量&a…

itchat 道歉_人类的“道歉”

itchat 道歉When cookies were the progeny of “magic cookies”, they were seemingly innocuous packets of e-commerce data that stored a user’s partial transaction state on their computer. It wasn’t disclosed that you were playing a beneficial part in a muc…

使用Kubespray部署生产可用的Kubernetes集群(1.11.2)

Kubernetes的安装部署是难中之难&#xff0c;每个版本安装方式都略有区别。笔者一直想找一种支持多平台 、相对简单 、适用于生产环境 的部署方案。经过一段时间的调研&#xff0c;有如下几种解决方案进入笔者视野&#xff1a; 部署方案优点缺点Kubeadm官方出品部署较麻烦、不够…

android webView 与 JS交互方式

webView 与JS交互 Android调用JS代码的方法有&#xff1a; 通过WebView的loadUrl&#xff08;&#xff09;通过WebView的evaluateJavascript&#xff08;&#xff09; 对于JS调用Android代码的方法有3种&#xff1a; 通过WebView的addJavascriptInterface&#xff08;&…

matlab软件imag函数_「复变函数与积分变换」基本计算代码

使用了Matlab代码&#xff0c;化简平时遇到的计算问题&#xff0c;也可以用于验算结果来自211工科专业2学分复变函数与积分变换课程求复角主值sym(angle(待求复数))%公式 sym(angle(1sqrt(3)*i))%举例代入化简将 代入关于z的函数f(z)中并化解&#xff0c;用于公式法计算无穷远点…

数据科学 python_为什么需要以数据科学家的身份学习Python的7大理由

数据科学 pythonAs a new Data Scientist, you know that your path begins with programming languages you need to learn. Among all languages that you can select from Python is the most popular language for all Data Scientists. In this article, I will cover 7 r…

[luoguP4142]洞穴遇险

https://www.zybuluo.com/ysner/note/1240792 题面 戳我 解析 这种用来拼接的奇形怪状的东西&#xff0c;要不就是轮廓线\(DP\)&#xff0c;要不就是网络流。 为了表示奇数点&#xff08;即\((xy)\%21\)&#xff09;的危险值&#xff0c;把该点拆为两个点&#xff0c;连一条边长…

飞信虚拟机

做完了一个图片处理软件,突然想到上次上网看到C#程序脱离.NET FRAMEWORK运行的文章,于是决定自己动手试一下。 之前看到有用别的方法来实现的&#xff0c;但我还是选择了现在比较流行的软件飞信中带的VMDotNet&#xff0c;也就是所谓的.NET FRAMEWORK虚拟机吧。相信有很多人也已…

django的contenttype表

https://blog.csdn.net/aaronthon/article/details/81714496 这篇文章已经非常详细了,供自己以后忘了...回看...... 总结&#xff1a; 当一张表和多个表FK关联&#xff0c;并且多个FK中只能选择其中一个或其中n个时&#xff0c;可以利用contenttype&#xff0c;固定用三个字段…

视频播放问题和提高性能方案

1.Five symptoms of poor video performance 1.1 视频加载缓慢 ​Perceived Wait Time Time to first frame (TTFF): ​ 播放开始所需的adaptive bitrate(ABR)流媒体段的数量。(我们稍后将对此进行更详细的讨论。) ​ 视频请求发送到视频加载之间的时间(即接收到足够的数据…

rabbitmq 不同的消费者消费同一个队列_RabbitMQ 消费端限流、TTL、死信队列

消费端限流1. 为什么要对消费端限流假设一个场景&#xff0c;首先&#xff0c;我们 Rabbitmq 服务器积压了有上万条未处理的消息&#xff0c;我们随便打开一个消费者客户端&#xff0c;会出现这样情况: 巨量的消息瞬间全部推送过来&#xff0c;但是我们单个客户端无法同时处理这…

动量策略 python_在Python中使用动量通道进行交易

动量策略 pythonMost traders use Bollinger Bands. However, price is not normally distributed. That’s why only 42% of prices will close within one standard deviation. Please go ahead and read this article. However, I have some good news.大多数交易者使用布林…

css3 变换、过渡效果、动画

1 CSS3 选择器 1.1 基本选择器 1.2 层级 空格 > .itemli ~ .item~p 1.3 属性选择器 [attr] [attrvalue] [attr^value] [attr$value] [attr*value] [][][] 1.4 伪类选择器 :link :visited :hover :active :focus :first-child .list li:first-child :last-chi…

webservice 启用代理服务器

您会发现你写完了一个webservice在调用的时候发现怎也没办法调用&#xff0c;一个简单的webservice怎么不能使用&#xff0c;一肚子的怨恨&#xff0c;哈哈您可能没有为webservice设置代理。 下面就给您写个调用的用例和大家分享下。其实很简单&#xff0c;但是你没有想到的时…

mysql常用的存储引擎_Mysql存储引擎

什么是存储引擎&#xff1f;关系数据库表是用于存储和组织信息的数据结构&#xff0c;可以将表理解为由行和列组成的表格&#xff0c;类似于Excel的电子表格的形式。有的表简单&#xff0c;有的表复杂&#xff0c;有的表根本不用来存储任何长期的数据&#xff0c;有的表读取时非…

android studio设计模式和文本模式切换

转载于:https://www.cnblogs.com/judes/p/9437104.html

高斯模糊为什么叫高斯滤波_为什么高斯是所有发行之王?

高斯模糊为什么叫高斯滤波高斯分布及其主要特征&#xff1a; (Gaussian Distribution and its key characteristics:) Gaussian distribution is a continuous probability distribution with symmetrical sides around its center. 高斯分布是连续概率分布&#xff0c;其中心周…

C# webbrowser 代理

百度&#xff0c;google加自己理解后&#xff0c;将所得方法总结一下&#xff1a; 方法1&#xff1a;修改注册表Software//Microsoft//Windows//CurrentVersion//Internet Settings下 ProxyEnable和ProxyServer。这种方法适用于局域网用户&#xff0c;拨号用户无效。 1p…

C MySQL读写分离连接串_Mysql读写分离

一 什么是读写分离MySQL Proxy最强大的一项功能是实现“读写分离(Read/Write Splitting)”。基本的原理是让主数据库处理事务性查询&#xff0c;而从数据库处理SELECT查询。数据库复制被用来把事务性查询导致的变更同步到集群中的从数据库。当然&#xff0c;主服务器也可以提供…