- 1,是干什么的,然后大致原理;
- 2,离线包组成;
- 3,工作原理;
- 3.1,下载原理
- 3.2,打开原理
- 3.2,cookie注意点
- 4,数据并行
WebPlugin是为了加速H5页面的展示速度,我们打开一个h5页面的流程大致如下
离线化插件的大致思路是将H5页面中的html、js、css以及一些静态的图片资源打包离线化至本地,在打开相应页面的时候从本地去打开,然后只需获取对应页面的数据,省去html、js、图片等资源的下载时间。
一个H5离线化插件一般对应某个业务。
离线化插件一般对应某个业务,这个业务通常包括多个H5页面。 离线化插件的内容主要包括两个方面:
- 1、多个H5页面中的html、js、css以及一些静态的图片资源
- 2、config.json文件。 config.json文件是插件配置文件,描述了这个插件中页面的名称和路径的映射关系
离线化插件工作的一个流程大概是是这样的:
- 1、通过运营平台上传我们打包好的离线化插件
- 2、服务端下发离线插件数据, 主要包括一个插件数组和一个总体md5值,每个插件对应:一个pluginid,唯一标识这个插件,也是作为这个插件下载的一个目录,一个插件下载的url,另外还有一个插件对应的md5值。 更新时机:app启动或者前后台切换的时候
主要的一个更新策略就是先去对比服务端下发的总体md5值和本地记录的总的md5值是否相同,相同就不更新,如果不同说明说明有更新,再去对比每个插件的m5值,对m5值改变的插件做更新,每个插件更新完成之后记录对应md5值,所有插件更新完成后记录总体md5值。
更新离线插件,可以先下载target.zip包,然后将其重命名为target_new.zip,然后解压,解压完成后,将旧的离线插件命名为target.temp,将新的离线包命名为target.zip,删除旧的离线插件临时文件target.temp,如果失败就恢复。
val aTmp = File(a.parent, "${a.name}.tmp")
if (a.exists()) {
if (!a.renameTo(aTmp)) {
throw IOException("Failed to rename a to temp")
}
}
if (!b.renameTo(a)) {
// 回滚
aTmp.renameTo(a)
throw IOException("Failed to rename b to a")
}
// 成功后删除临时文件
if (aTmp.exists()) {
aTmp.delete()
}
}
紧急更新,先检查是否有当离线包的下载任务,并判断是否已经开始下载,如果没开始就删除这个任务,然后开启一个紧急任务去下载这个离线包;如果开始了就给这个任务添加一个监听器,监听完成,完成后重新打开这个离线包。
插件下载完成之后,我们就可以从本地进行打开: 打开的一个流程大概是这样的:
一个打开plugin的bdwm协议是这样的: demo://plugin?pluginId=xxx&pageName=xxx
-
(1)根据pluginId,获取该插件的目录
-
(2)读取config.json配置文件。
-
(3)根据的pageName,可以查找到对应页面的pagePath;
-
(4)构造出一个以file开头的h5文件的路径,然后使用webview去打开 在打开的过程中需要请求这个页面的数据 这个时候有两种情况:
-
第一:页面不需要cookie信息,那么由这个页面自己发送网络请求
-
第二:页面需要cookie信息,webview在加载url的时候会根据url的域自动带上本地cookie信息
但是我们现在加载的是以file开头的一个路径,这个路径中是没有域的,所有webview是没法带cookie的。 解决方式是h5调用我们native的网络请求能力,native网络请求中去带上cookie,然后把请求到的数据传递给h5页面。
为了进一步加快离线包的页面显示速度,还为这个离线包做了数据预加载的优化,让webview的打开过程和h5页面的数据加载过程并行。
数据预加载前提:
在离线包的config.json文件中为需要预加载的页面,添加预加载数据PreloadRequest,主要包含预加载的url,请求方法,请求参数等。
大致流程是:
-
1、在webview打开页面同时,通过pluginId找到对应插件的config配置文件,读取相应页面的预加载数据。
-
2、根据这个预加载数据使用我们本地的okhttp网络请求框架去请求数据,然后将结果传递给h5页面,h5页面收到后就可以数据刷新。
-
(3)当数据获取成功,如果jsbridge注入完成,则调用其回调方法PreloadFinish,将获取到的数据传递给h5页面;如果jsbridge未注入完成,则将获取的数据缓存到内存,待jsbridge注入完成,在其注入完成的回调中,调用h5页面的回调方法PreloadFinish将数据传递给h5页面。h5页面收到数据后,并可根据数据去填充页面。