热更新原理总结

Instant Run概述

Instant Run 是 Android Studio2.0 之后新增的一个运行机制,能够减少开发人员第二次及以后的构建时间。

在没有Instant run之前,编译部署应用程序的流程如下图:

在这里插入图片描述
传统的编译部署,需要重新安装APP和重启 APP。这样会很耗时。

使用Instant Run会避免这一情况。

Instant Run基于更改的部分进行构建和部署。

在这里插入图片描述
Instant Run部署有三种方式,Instant Run会根据代码的情况来决定采用哪种部署方式。

  • hot swap——修改一个现有方法中的代码时会采用hot swap,他不需要重启当前Activity即可实现使更改的代码运行
  • warm swap——修改现有资源文件时采用warm swap,他需要重启Activity。
  • cold swap——当增删改一个字段、方法或类时会采用cold swap。他需要重启APP。

Gradle Transform

Gradle Transform是Android官方提供给开发者在项目构建阶段即由class到dex转换期间修改class文件的一套api。

Instant Run修复原理

  • 当第一次构建APP时,Instant Run利用Transform API在每一个类中注入一个叫change的字段
  • change实现了incrementalChange接口。
  • 在每一个方法中添加一个逻辑判断,如果change不为空就执行change的accessdispatch方法,否则执行原方法的逻辑。
  • 当我们修改完对应的代码点击run后,Instant Run会生成对应的patch文件。
  • patch文件中补丁类的名字是修改类的名字+$override,这个类实现了IncrementalChange接口
  • 同时生成一个AppPatchsLoaderImpl类,这个类维护着一个所有修改过的类的列表
  • 通过AppPatchsLoaderImpl将修改过的类中的change字段赋值为生成的xxx$override。

这样就实现了对代码的修改。

ClassLoader 修复代码

类加载方案基于Dex分包方案。

65535限制

Android系统有一个65536限制,意思是应用中引用的方法数不能超过65536个。

产生一个限制的原因是Dalvik Bytecode的限制,Dalvik指令集的方法调用指令invoke-kind索引为16bite,最多应用65536个方法。

LinearAlloc限制

Dalvik中的LinearAlloc是一个固定的缓冲区,当方法数超出了缓存区的大小时会报错。

针对这两个限制,产生了Dex分包方案。Dex分包方案主要做的是在打包时将应用代码分成多个Dex。

将应用启动时必须用到的类和这些类的引用类放到主Dex,其他代码放到次Dex,当应用启动时先加载主Dex,等到启动后再动态加载次Dex。

我们都知道,Android的类加载主要有两个:PathClassLoader和DexClassLoader,他们都是BaseDexClassLoader 的子类。

其中PathClassLoader在应用启动时创建,用于加载apk的dex文件。

DexClassLoader可以加载SD卡上包含dex的.jar和.apk文件。

BaseDexClassLoader 有个字段private final DexPathList pathList,BaseDexClassLoader 的findClass()、findResource()均是基于pathList实现的。

DexPathList 里面有一个Element数组,Element内部封装了DexFile ,DexFile用于加载dex文件,所以每个dex文件对应一个Element。

当通过BaseDexClassLoader 查找一个类时,会通过以下路线进行查找:

  • 调用 BaseDexClassLader 的 findClass(String name)方法
  • 接着交给 DexPathList 的findClass()方法
  • 然后遍历Element数组,调用Element的findClass()方法
  • Element的findClass()方法内部调用DexFile的loadClassBinaryName方法查找类。

当查找到了就直接返回,没有找到就去下一个Element查找。

所以,根据上述的查找流程,我们只需将我们修复后的类打包成Dex文件,存放到Element数组的最前面,这样就会优先从修复后的dex中查找并返回

在这里插入图片描述
具体操作的步骤就是

  • 获得APP的PathClassLoader
  • 通过dex包路径和父加载器创建我们的DexClassLoader
  • 反射得到两个加载器的pathList
  • 反射得到两个pathList的dexElements<
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值