Skip to content

Latest commit

 

History

History
188 lines (101 loc) · 12.6 KB

InstantRun详解.md

File metadata and controls

188 lines (101 loc) · 12.6 KB

InstantRun详解

之前在写AndroidStudio提高Build速度]这篇文章的时候写到,想要快,就用Instant Run。最近有朋友发来邮件讨论它的原理,最近项目不忙,索性就来系统的学习下。

Android Studio2.0开始引入了Instant Run,它主要是在RunDebug的时候可以去减少更新应用的时间。虽然第一次Build的时候可能会消耗稍长的时间来完成,但是Instant Run可以把更新内容推送到设备上,而无需重新build一个新的apk,这样就会很快速的让我们观察到改变。

Instant Run只支持在build.gralde文件中配置的Gradle版本是2.0.0以上并且minSdkVersion是15以上才可以。为了能更好的使用,请将minSdkVrsion设置到21以上。

部署完应用后,会在Runimage(或者(Debugimage))图标上面出现一个小黄色的闪电符号,这就意味着Instant Run已经准备就绪,在你下次点击按钮的时候可以推送更新内容。它不需要重新构建一个新的APK,它只推送那些新改变的地方,有些情况下app都不需要重启就可以直接显示新改变的下效果。

配置你的应用来使用Instant Run

Android Stuido中项目使用Gralde2.0.0及以上版本会默认使用Instant Run
让项目更新到最新的版本:

  1. 点击Settings中的Preferences按钮。
  2. 找到Build,Execution,Deployment中的Instant Run然后点击Update Project,如果Update Project部分没有显示,那说明你当前已经是最新版本了.
    image

修复类型

Instant Run通过热修复、暖修复或者冷修复来推送改变的代码和资源到你的设备或者模拟器上。它会根据你更改的内容来自动选择对应的修复类型。

  • 热修复: 更改的内容不需要重启应用甚至不需要重启当前的activity就可以让显示内容的改变,对于大部分通过方法内容改变的更改都可以通过这种方式来修改。
  • 暖修复: 需要重启activity才能让改变生效,在改变资源时会通过该方式。
  • 冷修复: 应用需要重启(不是重新安装)。对于一些方法方法结构和实现等结构性的改变需要通过该方式。

那具体更改内容和修复方式是怎么对应的呢?

  • 改变现在已经存在的方法
    这将通过热修复来执行,这是最快的一种修复方式。你的应用会在运行的过程中,在下次调用该方法时直接使用新实现的方法。 热修复不需要重新初始化对象。在看到具体的更改之前,你可能会需要重启当前的activity或者应用。默认情况下Android Studio在执行热修复后会自动重启当前的activity。如果你不想要它自动重启activity你也可以在设置中禁用。

  • 更改或者移除已经存在的资源
    这将通过暖修复来执行:这也是非常快的,但是Instant Run在推送这些更新内容时必须要重启当前的activity。你的应用仍然会继续运行,但是在重启activity时屏幕可能会闪动-这是正常滴。

  • 结构性的改变例如:

    • 增删或者改变:

      • 一个注解
      • 一个变量
      • 一个静态变量
      • 一个方法结构
      • 一个静态方法结构
    • 更改该类集成的父类

    • 更改接口的实现列表

    • 更改类的静态修饰符

    • 使用动态资源id重新布局

    上面的这些改变都将通过冷修复(API 21以上才支持)来执行.冷修复会稍微有些慢,因为虽然不需要构建一个新的APK但是必须要重启整个app才能推送这些结构性的代码改变。对于API 20及以下的版本,Android Studio将重新部署APK

  • 更改manifest文件或者更改manifest文件中引用的资源或者更改Android桌面widgetUI实现(需要Clean and Rerun)
    在更改清单文件或者清单文件中引用的资源时,Android Studio会自动的重新部署引用来实现这些内容的改变。这是因为例如应用名称、图标和intent filters这些东西是要在应用安装到设备时根据清单文件来决定的。 在更新Android UI widget时,你需要执行Clean and Rerun才能看到更改的内容,因为在使用Instant Run时执行clean会需要很长的时间,所以你在更新UI widget时可以禁用Instant Run

使用Rerun

如果修改了一些会影响到初始化的内容时,例如修改了应用的onCreate()方法,你需要重启你的应用来让这些改变生效,你可以点击Rerun图标。它将会停止应用运行,并且执行clean操作后重新部署一个新的APK到你的设备。

实现原理

正常情况下,我们修改了内容,想让让它生效,那就需要如下的步骤:

image

Instant Run的目标也非常简单:

尽可能多的移除上面的步骤,来让剩下的部分尽可能更快。

这就意味着:

  • 只构建和部署新更改的部分。
  • 不去重新安装应用。
  • 不去重启应用。
  • 甚至不去重启activity

image

普通情况下在你点击Run或者Debug按钮时,会执行如下的操作:
image

清单文件会被整合然后与你应用的资源重启打包成APK.同样的,.java的源代码会被编译成二进制,然后转换成.dex文件,他们也会被包含到APK中。

在使用Instant Run的情况下,第一次点击RunDebugGradle会执行一些额外的操作:
image instrumentation相关的二进制内容会被增加到.class文件中,并且一个新的App Server类会被注入到应用中。
同时也会增加一个新的Application类,来注入一些自定义的class loader并且能启动App Server。因此minifest文件会被修改来保证使用该新加的Application类(如果你已经创建了自己的Application类,Instant Run的版本将会用你定义的来进行代理扩展)

经过上面的操作Instant Run就开始执行了,以后如果你改变了代码部分,在重新点击Run或者Debug时,Instant Run将会通过热、暖、冷修复来尽可能的减少上面的构建过程。

Instant Run更改内容前,Android Studio会你的应用版本是否支持Instant Run并且App Server是否运行在对其有用的端口(内部使用了Socket)。 这样来确定你的应用是否在前台运行,并且找到Studio所需要的构建ID.

总结一下,其实就是内部会对每个class文件注入instant run相关的代码,然后自定义一个application内部指定自定义的classLoader(也就是说不使用默认的classLoader了,只要用了Instant Run就需要使用它自定义的classLoader),然后在应用程序里面开启一个服务器,Studio将修改的代码发送到该服务器,然后再通过自定义的classLoader加载代码的时候会去请求该服务器判断代码是否有更新,如果有更新就会通过委托机制加载新更新的代码然后注入到应用程序中,这样就完成了替换的操作。

热修复过程

image

Android Studio会监听在开发过程中哪个文件发生了改变,并且通过一个自定义的Gralde task来只对修改的class文件生成对应的.dex文件。
这些新的.dex文件会通过Studio传递发布给应用中运行的App Server

因为开始时这些文件的class已经存在到运行中的应用中-Gralde需要保证更新的版本来保证他们能覆盖之前已经存在的文件。这些更新文件的转换是由App Server通过自定义的class loader来完成的。

从现在开始,每次一个方法被调用时(不管在应用中的任何地方),被注入到最初的class文件中的instrumentation都讲去连接App Server来检查它们是否有更新了。 如果有更新,执行操作将被指派到新的充在的class文件,这样就会执行新修改的方法。

image

如果你设置断点,你会发现你调用的是override名字的类中的方法。 image

这种重新指定方法的方式在改变方法实现时非常有效,但是对于那种需要在Activity启动时加载的改变呢?

暖修复

暖修复会重启Activity。资源文件会在Activity启动时被加载,所以修改它们需要activity重新启动来进行加载。

现在,更改任何资源都会导致所有的资源都被重新打包病转移到应用中-但是以后会支持增量包的功能来让只打包和部署那些新修改的资源。

注意,暖修复在更改manifest件或者manifest文件中引用的内容时无效,因为manifest文件中的内容需要在apk安装时读取。更改Manifest文件(或者它所引用的内容)需要被全部构建和部署。

非常不幸的是,重启activity在做一些结构性的改变时无效。对于这些改变需要使用冷修复。

冷修复

在部署时,你的应用和他的子项目会被分派到10个不同的部分,每个都在自己单独的dex文件。不同部分的类会通过包名来分配。在使用冷修复时,修改的类需要其他所有相关的class文件都被重新打包后才能被部署到设备上。
这就需要依赖Android Runtime能支持加载多个.dex文件,这是一个在ART中新增的功能,它只有在Android 5.0(API 21)以上的设备总才支持。
对于API 20一下的设备,他们仍在使用Dalvik虚拟机,Android Studio需要部署整个APK

有些时候通过热修复来改变的代码,但是它会被应用首次运行时的初始化所影响,这时你就需要restart你的应用来让其生效(快捷键是Command + Ctrl + R)。
image

Instant Run使用技巧及提示

Instant Run是由Android Studio控制的,所以你只能通过IDEstart/restart你的debug实例,不要直接在设备中start/restart你的应用,不然的话就会发生错乱。

Instant Run限制条件
  • 部署到多个设备

    Instant Run针对设备的不同API Level使用不同的技术来进行热、暖、冷修复。因此,如果同时部署一个应用到多个设备时,Studio会暂时关闭Instant Run功能。

  • Multidex

    如果你的项目支持传统的Multidex-也就是在build.gradle中配置了multiDexEnabled trueminSdkVersion 20及以下-当你部署应用到4.4以下的设备上时,Android Studio将会禁用Instant Run

    如果minSdkVersion设置为21或者更高时,Instant Run将自动配置来支持multidex,因为Instant Run只支持debug版本,有需要在发布release版的时候配置你的build变量来支持multidex

  • 使用第三方插件 Android Studio在使用Instant Run时会暂时禁用Java Code Coverage LibraryProGuard。因为Instant Run只支持debug版本,这样也不会影响release版的构建。

  • 只能在主进程中运行
    目前热修复只能在主进程中进行,如果在其他进程中热、暖修复将无法使用,只能用冷修复来替代。

参考: