本篇文章我们主要围绕以下几个内容展开
一、什么是热更新
二、热更新原理
三、目前市场上热更新框架的对比
四、热更新实践(Sophix)
一、什么是热更新
用来紧急修复线上版本的bug,而且是在用户无感知的情况下,自动修复bug。我们之前的一个开发流程是,开发-测试-发包-审核-通过,那如果对于刚上线的版本,突然间发现出现了一个致命的闪退问题,那又得重复这样的流程,到最终提示用户下载新的版本并安装,即可修复该bug。但是一个一行代码解决的bug,就要重新走整个流程,一个是太耗费人工成本,另一个是用户体验也很不好。为了解决这样的问题,热修复就出现了,当线上的版本出现了紧急的bug之后,开发人员只需要将bug修改完之后,打出补丁包,并将补丁包进行下发,这样就可以在用户不知道的情况下,直接修复了bug。从而大大节约了时间成本。
二、热更新的原理
代码修复主要有三个方案,分别是底层替换方案、类加载方案和Instant Run方案。
QZone和Tinker热修复原理
在讲解这两个热修复原理之前,我们先来回顾下之前讲的Android类加载机制,我们知道,Android中要加载某一个类,最终都是调动DexPathList中的findClass()方法
public Class findClass(String name, List<Throwable> suppressed) {
for (Element element : dexElements) {
DexFile dex = element.dexFile;
if (dex != null) {
Class clazz = dex.loadClassBinaryName(name, definingContext, suppressed);
if (clazz != null) {
return clazz;
}
}
}
if (dexElementsSuppressedExceptions != null) {
suppressed.addAll(Arrays.asList(dexElementsSuppressedExceptions));
}
return null;
}
}
从中我们可以看出,加载一个类的时候,都会去循环dexElements数组取出里面的dex文件,然后从dex文件中找目标类,只要目标类找到,则直接退出循环,也就是后面的dex文件就没有被取到的机会。那我们就可以根据这样的一个原理,将修改后的类编译后统一放在patch.dex补丁文件中,通过反射将patch.dex放在dexElemets这个数组的第一个元素,这样,当加载出现bug的类时,首先会先从patch.dex这个文件中去找,因为我们将修改后的类放在了patch.dex文件中,所以肯定会被找到(此时加载到的是已经修复的类),一旦被找到,后面dex中的bug类就没办法被加载到,这样就实现自动修复bug的目的了。虽然两者的原理是类似的,但Tinker是在QZone的基础上进行了改进。
QZone的修复流程:
把BUG方法修复以后,放到一个单独的DEX里,插入到dexElements数组的最前面