InstantRun是如何工作的

原文地址

Instant Run: How Does it Work?!

Instant Run是Android Studio上可以称之为魔法的一个黑科技,在代码更改时能大大的减少你重新构建部署的时间。之所以称之为黑科技,是因为它的表现实在是太好了,当我们第一次点击run或者debug的时候,可能在时间上和不开启没有区别,但是当我修改代码后重新run的时候,速度之快可能在我来不及看运行设备的时候已经成功的部署完毕。

以一个简单的构建循环流程图开始

构建,部署,安装,app启动,activity启动

Instant Run的目标十分的简单:

尽可能多的移除中间的步骤,剩下的步骤越快越好

在实际使用中意味着:

  • 构建和部署只基于增量改变
  • 不重装app
  • 不重启app
  • 甚至不重启 Activity

Hot, Warm, and Cold Swaps三种概念

Instant Run =增量构建 + Hot, Warm, or Cold swap

Hot swap:代码的增量改变不需要重启一个app甚至是当前的activity就能成功生效,在大部分方法实现的更改上采用的是这种方式
Warm Swap: 在修改可以被生效和看到之前这个当前Activity需要重新启动,一般是在资源的改动上会采取这种方式
Cold Swap: 这个App会重新启动,不是重新安装,一般是在结构的改变时采取,比如一个类的继承接口或者签名改变

当点击Run或者Debug时,步骤是这样的

Manifest被合并并且联合资源文件以及dex打包到apk中

所有的 Manifests 文件会随着应用程序的资源文件被合并并且打包,同样的,你的java源码文件会被编译成字节码然后通过dex过程转化为 .dex 文件也一起打包到APK中。

开启Instant Run功能第一次点击Run或者Debug,Gradle增加了一些额外的tasks

Instrumentation和App Server被注入到debug APK

Bytecode instrumentation(译者注:改变编译器生成的类的字节码)被添加到了 .class 文件中而且一个新的 App Server被注入到app中。除此之外,一个新定义的Application类也被加进去,它注入了一个自定义的classLoader(类加载器)并且会启动前面的App Server。
因此,你的 manifest 文件被修改为使用这个新的Application,如果你已经创建了自己的Application类,那么Instant Run会实现一个代理。
Instant Run启动之后,如果你修改的代码并且重新点击了run或者debug,Instant Run会尽可能的选择一种过程较少的构建过程,当然根据修改的影响程度不同会有三种不同方式,hot swap(热拔插),warm swap(温拔插)以及cold swap(冷拔插)。

在Instant Run使用之前,Android Studio会检测是否存在一个正在运行的App Server并且可以支持Instant Run的socket连接,这也同时能确保这个app正运行在前台,Android Studio能正常工作。

热拔插

如图所示,Android Studio monitors会 针对改变的文件运行一个自定义的Gradle task来生成一个 .dex 文件,Android Studio会提取这些 .dex 文件并且将他们部署到运行的App Server中。
因为原始版本的类都已经存在运行程序中,Gradle会转化 这些更新的类并且使它们有效的覆盖那些已经存在的类。这些转化更新的类会被App Server中的自定义类加载器来加载。
就像下面这张图显示的一样

transformed的说明已经引用摘抄在下面

Starting with 1.5.0-beta1, the Gradle plugin includes a Transform API allowing 3rd party plugins to manipulate compiled class files before they are converted to dex files.(The API existed in 1.4.0-beta2 but it's been completely revamped in 1.5.0-beta1)
The goal of this API is to simplify injecting custom class manipulations without having to deal with tasks, and to offer more flexibility on what is manipulated. The internal code processing (jacoco, progard, multi-dex) have all moved to this new mechanism already in 1.5.0-beta1.
Note: this applies only to the javac/dx code path. Jack does not use this API at the moment.
The API doc is here.
To insert a transform into a build, you simply create a new class implementing one of the Transform
interfaces, and register it with android.registerTransform(theTransform)
or android.registerTransform(theTransform, dependencies).
Important notes:

  • The Dex class is gone. You cannot access it anymore through the variant API (the getter is still there for now but will throw an exception)
  • Transform can only be registered globally which applies them to all the variants. We'll improve this shortly.
  • There's no way to control ordering of the transforms.
    We're looking for feedback on the API. Please file bugs or email us on our adt-dev mailing list.

从现在开始,每一次应用内方法的调用,都会被注入进来的instrumentation和App Server来监听这个方法是否已经更新,如果已经更新,调用会被代理到新“重写”的类上,然后新的版本的方法会替代以前老的方法。

Instant Run Debug

看上面这个动态图中的操作,在修改了 enableLocationUpdates 中的字段后,可以看到黄色圈圈中我们的MainActivity的后面加上了一个 $override 的字样。
修改一个方法的实现能正常的通过热拔插来正常的工作,但是如果是修改了在activity开始创建中的内容呢?

温拔插

温拔插需要重启整个Activity。资源在Activity启动的时候被加载进来,所以当修改他们的时候需要重新启动Activity来强制资源重新加载。
现在任意资源文件的修改都会导致所有的资源被重新打包发送给App,但是Instant Run通过提供一个增量包,用来打包和部署新的或者已经修改的资源文件。

注意:这个温拔插在修改Manifest中的资源文件引用的时候不能生效,因为资源文件的值在APK被安装的时候就已经读取了,当我们改变Manifest文件或者Manifest引用资源的时候,Android Studio还是会执行全部文件的编译和部署。

不幸的是,重启Activity也就是温拔插的方式,并不适用于结构的改变,比如添加,删除或者改变annotations,fields,static和方法实例甚至是改变父类或是静态初始化都会导致第三个阶段,冷拔插。

冷拔插

当应用部署的时候,你的app和子项目会被分割成10个切片,每一个都有自己的dex文件,所有的类根据他们自己的包名被分配到不同的切片中,当进入冷拔插状态时,如果一个类被改变了,那么在重新部署的时候同一切片下的所有的类都需要重新打包成dex文件。
这个方法依赖于Android在运行时加载多个dex文件的功能,这个功能在ART虚拟机上被提出来,这个ART虚拟机虽然在4.4的版本中就已经被加入,但是实际上在5.0开始才真正的取代了Dalvik虚拟机,所以在5.0以下的设备,Android Studio采取的是全部编译部署的形式。

Instant Run的小瑕疵

虽然Instant Run已经足够聪明,能根据不同的场景来采用不同的方式构建,但是有时候代码修改后虽然采取了热拔插的方式,但是一些只有在application第一次启动时初始化的操作并不能影响到,比如下面这个例子,虽然我们已经修改了里面的值,但是通过Instant Run启动的数据并没有变化,这种情况就需要重新启动app来让它生效。

To perform an incremental build and restart the app, click Rerun (CTRL-CMD-r) from the toolbar.

Instant Run提示和小技巧

Instant Run完全由Android Studio来控制,所以在debug时只通过IDE上的start / restart来启动,最好不要直接通过设备来启动,可能

更详细的小技巧清单tips and tricks,这都是Android官方的文档但是只有少量有价值的东西

  • 调整你分配给Gradle进程的资源。在 gradle.properties 文件中合理的设置 jvmargs 参数会显著的提高编译的速度,无论是Instant Run还是全部编译。你可以进行试验并观察构建时间的影响,就能发现这个的价值。
  • 因为ART虚拟机从21版本才开始正式启用,在debug调试的时候将 minSdkVersion 设为21或者更高会充分发挥Instant Run的编译速度。
  • 牢记改变manifest文件会导致全部的编译和部署,速度会很慢,所以,如果你的构建过程会自动的更新manifest的任何部分,比如会自动的改变versionCode和versionName,在debug时最好关掉这个行为。
  • Instant Run现在只作用于主进程,所以如果你的应用使用多进程,热拔插和温拔插在其他的进程会退化成冷拔插的操作甚至是整体全部的编译如果target API在21以下。
  • 如果在Windows下开发,Windows Defender Real-Time Protection可能会导致Instant Run挂掉,可以通过添加白名单列表的方式来解决。
  • 截至该文之前,暂时不支持Jack compiler,Instrumentation Tests,或者同时部署到多台设备上。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,567评论 25 707
  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    passiontim阅读 15,085评论 2 44
  • 凌晨一点。刚回到住的地方,对于一个N年不跑步今天跑了五公里的人来说。已经累炸。 脑子里有很多东西在转,好吧。我承认...
    鲸鱼蓝阅读 78评论 0 0
  • 导读:现在这个社会,用以前的方法想成功很难了,如果你学会了策划,那么希望很大。策划不是狭义上的,而是广义上的 。 ...
    飞驰的死兔子阅读 766评论 0 0
  • 开篇 现在网盘如山倒, 网盘一个一个都开始关闭了. 是时候做一个自己的个人云储存了.市面上适合个人用的的 nas ...
    yww阅读 1,932评论 0 4