Instant Run浅析

Instant Run


Instant run是在android studio 2.0引入的,能让我们快速构建运行app。其中包含了四种情况:hot swap、warm swap、cold swap以及无法使用instant run的情况。下面部分引用官方文档进行说明:
* hot swap
This is the fastest type of swap and makes changes visible much more quickly. Your application keeps running and a stub method with the new implementation is used the next time the method is called.
只对已存在的方法实现进行修改时支持hot swap,这种情况无需重启app或者是activity。但如果当前app被切换了,则会退化到cold swap。

* warm swap
This swap is still very fast, but Instant Run must restart the current activity when it pushes the changed resources to your app.
对已存在的资源文件进行修改时支持warm swap,这种情况需要重启当前activity。

* cold swap
This swap is a bit slower because, although a new APK is not required, Instant Run must restart the whole app when it pushes structural code changes.
For target devices running API level 20 or lower, Android Studio deploys a full APK.
对成员变量、注解、方法签名进行增删改时支持cold swap,需要重启app。

* new build
When making changes to the app’s manifest or resources referenced by the manifest, Android Studio automatically deploys a new build in order to apply these changes. This is because certain information about the app, such as its name, app icon resources, and intent filters, are determined from the manifest when the APK is installed on the device.
对manifest等进行修改,或者usb断开,则无法使用instant run。

编译

  • 首次编译
    1. 将instant-run.jar编译成dex,打入apk。
    2. 修改manifest文件,将application替换为instant-run.jar中的BootstrapApplication。
    3. app的所有类都添加类型为IncrementalChange的 change change字段不为空则调用 changeaccess dispatch方法并返回。编译出来的dex都将打包到instant-run.zip并打入apk。
  • 非首次编译
    • hot swap
      根据修改的类生成一个新的实现IncrementalChange接口的新类,类名称为原名称加上$override,里面的方法大部分来自修改过后的类。以及生成对应的AppPatchesLoaderImpl,记录所有修改的类原名称。
    • warm swap
      生成新的resources.arsc
    • cold swap
      重新生成修改类对应的dex

启动

由于首次编译时application已被替换成BootstrapApplication,启动的application自然也是它,重点关注attachBaseContext和onCreate两个方法:
1. attachBaseContext
- 调用createResources方法判断资源文件是否需要更新,并将资源文件的路径保存到externalResourcePath
- 调用setupClassLoaders将PathClassLoader的parent设置为IcreamentalClassLoader,而IcreamentalClassLoader的parent则设置为PathClassLoader的原parent即BootClassLoader,并且通过DelegateClassLoader代理完成findClass工作。相当于在PathClassLoader和BootClassLoader之间插入了一个DelegateClassLoader。此时instant-run.zip里面所有的dex以及后续修改代码生成的dex都已经在data/data的cache目录下,DelegateClassLoader会去这个目录进行class的加载。
- 调用createRealApplication创建实际的Application
2. onCreate
- 调用MonkeyPatcher#monkeyPatchApplication把刚才创建的application设置到ActivityThread中去,并把LoadedApk、资源文件以及application关联起来
- 调用MonkeyPatcher.monkeyPatchExistingResources根据externalResourcePath生成新的AssetManager,并将其设置到相关的对象中去(如Resources实例的mAssets变量)。
- 启动一个Server来与ide交互

部署

部署的工作都集中在onCreate中启动的Server中。
- hot swap

如果收到的文件名是classes.dex.3,则表明这是一次hot swap,调用handleHotSwapPatch来进行部署。这个方法主要做的事情就是根据AppPatchesLoaderImpl实例化所有修改后的类,并赋值给对应原类的 change change字段不为空,实际执行的就是修改后的方法。
- warm swap

如果收到的文件名为esources.ap_或以res/开头,则表明是warm swap,调用handleResourcePatch来进行部署。直接将资源文件写入,并重启当前activity。
- cold swap

如果收到的文件名以.dex结尾,则表明是cold swap,调用handleColdSwapPatch进行部署。直接将dex文件写入,重启app。

局限

  • 无法同时部署到多个设备上
  • 如果设置了multiDexEnabled则无法部署到4.4及以下的设备上
  • 有性能影响
  • 可能对需要操作bytecode的第三方插件造成影响
  • hot swap和warm swap只对主进程生效,其他进程会退化成cold swap

参考

  1. About Instant Run
  2. 深度理解Android InstantRun原理以及源码分析

你可能感兴趣的:(Android)