- ·上一篇文章:日本便利店将引入无人收银系统
- ·下一篇文章:一加宣布安卓更新计划:2年重大系统版本
深度剖析 | 阿里热修复如何精简优化补丁资源?
张新包索引到补丁包索引的映射表:对于全局值字符串池的处理也是类似,不同地方在于,我们需要进一步解析每个资源项,得到其对应的具体字符串值,仍然是以这个资源为例:我们需要找到的,就是app_name在0x7f包键字符串的索引,以及MyDemo在全局值字符串中的索引。另外,我们还需要处理样式。样式是字符串的特殊格式,比如下面的这个资源这里的Demo字符串就拥有加粗的样式,而某个字符串对应的样式的在样式表中的索引值与这个字符串在字符串池中的索引值是一样的。aapt在编译的时候也会将带有样式的资源全部放到字符串池的最前面。比如有五个字符串具有样式,这五个字符串就会被默认放到字符串池的前五个,而样式表也只有五个样式,分别对应了这前五个字符串。而从第六个字符串以后,就没有样式了。所以,这里我们还需要调整样式表,把收集到的字符串所对应的样式也一同移动到对应位置。此外,样式字符串,也就是例子中的b字符串实际上也是保存在字符串池中的,因此,当使用到某个样式的时候,还需要将该样式的字符串索引添加到我们的索引映射表中并重新编排。重新编排与调整偏移值我们用一张示意图来描述这个编排过程:其中深色offset entry的表示补丁中实际有效的字符串所对应的偏移值,可以看到,其中的新包中entries按照前面安排的映射关系移动到了补丁entries的相应位置,并且entries的偏移值也根据新排布的字符串位置进行了调整。下方的字符串块strings和样式块styles的内容也只保留有效部分,这样,所有有效字符串紧贴在了一起,并去除了新包中其他无用的资源,大幅节省了空间。最后需要重新构造字符串的头部ResStringPool_header结构,使得其中的各个字段(stringCount、styleCount、stringsStart、stylesStart等)填入正确的值。这样,一个有效的补丁字符串池就完整构建好了。这个重排的过程对于键值两种字符串池是完全相同的。修正资源引用处字符串池构建完毕了以后,还需要对资源中使用到这些字符串的地方进行重新索引。显然,只需要根据这个映射表:把原来的老索引值修正为新索引值就行了。具体来说,就是将资源文件结构中的ResTable_entry(代表资源项)和Res_value(代表具体资源的值)中,类型为ResStringPool_ref的字段的index值修正过来即可。由于我们压缩优化的是resources.arsc中的字符串池,因此需要完整地遍历每个补丁资源项,把相应的index做替换。而xml中的资源不需要相应修改,因为xml中使用到的只有arsc里面的资源id,感知不到id对应的字符串是什么,所以只要在arsc中处理好,xml自然就能找到id所持有的正确的字符串。总结通过这三个步骤,便实现了字符串池的精简。当然处理过程中还有有很多零碎的问题,比如引用类型资源的处理、Map资源项和字符串池各个块的拼接等等,这些都需要十分细致地处理好,否则都会导致运行时解析格式失败而崩溃。本文没有述及这些繁琐的问题,也是为了不因为它们而扰乱了主要处理逻辑,当搞定了主干后,回头再收拾这些细枝末节就显得游刃有余了。精简后效果是很明显的,不过具体还是取决于原始APK中资源字符串的数量以及补丁资源中实际有效的字符串的数量,如果资源字符串较多的话会有非常显著的优化。我们遇到最极端的一个例子是,精简之前带资源的补丁有4M大小,而精简之后直接变为23K!由此可见一斑。目前Sophix最新版本打包工具的高级选项中已默认开启这个优化资源补丁选项,立刻使用就能为你的资源热修复补丁瘦身。当然,还有一些其他选项开关,是为了打包的灵活性而设置的,其中有些强烈建议打开的选项我们已经默认开启了。Sophix热修复中还有许多技术优化点,我们也在去年7月推出了《深入探索Android热修复技术原理》免费电子书,详细讲解了代码、资源、动态库的热修复实现(在阿里技术公众号,回复“热修复”,即可下载)。值此一周年之际,我们与电子工业出版社合作,计划在近期出版该书的印刷纸质版,并新增了一些篇章,以方便大家翻阅,敬请期待。最后,手淘基础平台部EMAS平台诚招Android高级开发工程师/专家,欢迎各位优秀靠谱的小伙伴加入,查看职位详情:https://job.alibaba.com/zhaopin/position_detail.htm?positionId=46817或者发送简历至xiaolin.gxl@alibaba-inc.com。每天一篇技术文章,看不过瘾?关注“阿里巴巴机器智能”微信公众号发现更多AI干货。
深度剖析 | 阿里热修复如何精简优化补丁资源?