社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
如果你交给某人一个程序,你将折磨他一整天;如果你教某人如何编写程序,你将折磨他一辈子。
热更新是一种各大手游等众多App常用的更新方式。简单来说,就是在用户通过App Store下载App之后,打开App时遇到的即时更新
说到热更新的原理,不得不提一下android中类的加载流程(这里感谢hi大头鬼hi写的一篇Android热更新实现原理文章)
我们知道Java在运行时加载对应的类是通过 ClassLoader 来实现的,ClassLoader本身是一个抽象来,Android中使用PathClassLoader类作为Android的默认的类加载器,PathClassLoader其实实现的就是简单的从文件系统中加载类文件。PathClassLoade本身继承自BaseDexClassLoader,BaseDexClassLoader重写了findClass方法。
该方法是ClassLoader的核心:
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
List<Throwable> suppressedExceptions = new ArrayList<Throwable>();
Class c = pathList.findClass(name, suppressedExceptions);
if (c == null) {
ClassNotFoundException cnfe = new ClassNotFoundException("Didn't find class "" + name + "" on path: " + pathList);
for (Throwable t : suppressedExceptions) {
cnfe.addSuppressed(t);
}
throw cnfe;
}
return c;
}
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;
}
this.dexElements = makeDexElements(splitDexPath(dexPath), optimizedDirectory,
suppressedExceptions);
makeDexElements所做的事情就是遍历我们传递来的dexPath,然后一次加载每个dex文件。
上面分析了Android中的类的加载的流程,可以看出来DexPathList对象中的dexElements列表是类加载的一个核心,一个类如果能被成功加载,那么它的dex一定会出现在dexElements所对应的dex文件中,并且dexElements中出现的顺序也很重要,在dexElements前面出现的dex会被优先加载,一旦Class被加载成功, 就会立即返回,也就是说,我们的如果想做hotpatch,一定要保证我们的hotpacth dex文件出现在dexElements列表的前面。
说的通俗一点,热更新就是通过动态替换dex的方式来实现修复代码的。
我们先来看一个项目正常的发布流程
这种发布流程的存在的问题:
有时候我们甚至修改了一两行代码也要重新发布一个新版本,这样不论是对用户,还是对开发人员来说,体验都是非常不好的。
而如果我们使用热更新,流程则如下:
可见,热更新能够以更低的成本,更灵活的方式应对Bug修复。
当然,热更新也是存在着缺陷的,不过目前来说热更新的利远远大于弊
就拿tinker的方案来说,它存在的已知缺陷就有以下几点:
对热更新的介绍暂时就到这里过,接下来我会写一篇关于Tinker方案的使用过程,以及注意事项!
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!