InstantRun是如何工作的

原文地址

Instant Run: How Does it Work?!

Instant Run是Android Studio上可以稱之為魔法的一個黑科技野来,在代碼更改時能大大的減少你重新構(gòu)建部署的時間晰搀。之所以稱之為黑科技却舀,是因為它的表現(xiàn)實在是太好了冀惭,當(dāng)我們第一次點擊run或者debug的時候,可能在時間上和不開啟沒有區(qū)別佃乘,但是當(dāng)我修改代碼后重新run的時候份蝴,速度之快可能在我來不及看運行設(shè)備的時候已經(jīng)成功的部署完畢。

以一個簡單的構(gòu)建循環(huán)流程圖開始

構(gòu)建衡未,部署尸执,安裝,app啟動缓醋,activity啟動

Instant Run的目標(biāo)十分的簡單:

盡可能多的移除中間的步驟剔交,剩下的步驟越快越好

在實際使用中意味著:

  • 構(gòu)建和部署只基于增量改變
  • 不重裝app
  • 不重啟app
  • 甚至不重啟 Activity

Hot, Warm, and Cold Swaps三種概念

Instant Run =增量構(gòu)建 + Hot, Warm, or Cold swap

Hot swap:代碼的增量改變不需要重啟一個app甚至是當(dāng)前的activity就能成功生效,在大部分方法實現(xiàn)的更改上采用的是這種方式
Warm Swap: 在修改可以被生效和看到之前這個當(dāng)前Activity需要重新啟動改衩,一般是在資源的改動上會采取這種方式
Cold Swap: 這個App會重新啟動岖常,不是重新安裝,一般是在結(jié)構(gòu)的改變時采取葫督,比如一個類的繼承接口或者簽名改變

當(dāng)點擊Run或者Debug時竭鞍,步驟是這樣的

Manifest被合并并且聯(lián)合資源文件以及dex打包到apk中

所有的 Manifests 文件會隨著應(yīng)用程序的資源文件被合并并且打包板惑,同樣的,你的java源碼文件會被編譯成字節(jié)碼然后通過dex過程轉(zhuǎn)化為 .dex 文件也一起打包到APK中偎快。

開啟Instant Run功能第一次點擊Run或者Debug冯乘,Gradle增加了一些額外的tasks

Instrumentation和App Server被注入到debug APK

Bytecode instrumentation(譯者注:改變編譯器生成的類的字節(jié)碼)被添加到了 .class 文件中而且一個新的 App Server被注入到app中。除此之外晒夹,一個新定義的Application類也被加進去裆馒,它注入了一個自定義的classLoader(類加載器)并且會啟動前面的App Server。
因此丐怯,你的 manifest 文件被修改為使用這個新的Application喷好,如果你已經(jīng)創(chuàng)建了自己的Application類,那么Instant Run會實現(xiàn)一個代理读跷。
Instant Run啟動之后梗搅,如果你修改的代碼并且重新點擊了run或者debug,Instant Run會盡可能的選擇一種過程較少的構(gòu)建過程效览,當(dāng)然根據(jù)修改的影響程度不同會有三種不同方式无切,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中噩峦。
因為原始版本的類都已經(jīng)存在運行程序中锭沟,Gradle會轉(zhuǎn)化 這些更新的類并且使它們有效的覆蓋那些已經(jīng)存在的類抽兆。這些轉(zhuǎn)化更新的類會被App Server中的自定義類加載器來加載。
就像下面這張圖顯示的一樣

transformed的說明已經(jīng)引用摘抄在下面

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.

從現(xiàn)在開始族淮,每一次應(yīng)用內(nèi)方法的調(diào)用辫红,都會被注入進來的instrumentation和App Server來監(jiān)聽這個方法是否已經(jīng)更新,如果已經(jīng)更新祝辣,調(diào)用會被代理到新“重寫”的類上贴妻,然后新的版本的方法會替代以前老的方法。

Instant Run Debug

看上面這個動態(tài)圖中的操作蝙斜,在修改了 enableLocationUpdates 中的字段后名惩,可以看到黃色圈圈中我們的MainActivity的后面加上了一個 $override 的字樣。
修改一個方法的實現(xiàn)能正常的通過熱拔插來正常的工作孕荠,但是如果是修改了在activity開始創(chuàng)建中的內(nèi)容呢娩鹉?

溫拔插

溫拔插需要重啟整個Activity攻谁。資源在Activity啟動的時候被加載進來,所以當(dāng)修改他們的時候需要重新啟動Activity來強制資源重新加載弯予。
現(xiàn)在任意資源文件的修改都會導(dǎo)致所有的資源被重新打包發(fā)送給App戚宦,但是Instant Run通過提供一個增量包,用來打包和部署新的或者已經(jīng)修改的資源文件锈嫩。

注意:這個溫拔插在修改Manifest中的資源文件引用的時候不能生效受楼,因為資源文件的值在APK被安裝的時候就已經(jīng)讀取了,當(dāng)我們改變Manifest文件或者Manifest引用資源的時候呼寸,Android Studio還是會執(zhí)行全部文件的編譯和部署艳汽。

不幸的是,重啟Activity也就是溫拔插的方式等舔,并不適用于結(jié)構(gòu)的改變骚灸,比如添加,刪除或者改變annotations慌植,fields甚牲,static和方法實例甚至是改變父類或是靜態(tài)初始化都會導(dǎo)致第三個階段,冷拔插蝶柿。

冷拔插

當(dāng)應(yīng)用部署的時候丈钙,你的app和子項目會被分割成10個切片,每一個都有自己的dex文件交汤,所有的類根據(jù)他們自己的包名被分配到不同的切片中雏赦,當(dāng)進入冷拔插狀態(tài)時,如果一個類被改變了芙扎,那么在重新部署的時候同一切片下的所有的類都需要重新打包成dex文件星岗。
這個方法依賴于Android在運行時加載多個dex文件的功能,這個功能在ART虛擬機上被提出來戒洼,這個ART虛擬機雖然在4.4的版本中就已經(jīng)被加入俏橘,但是實際上在5.0開始才真正的取代了Dalvik虛擬機,所以在5.0以下的設(shè)備圈浇,Android Studio采取的是全部編譯部署的形式寥掐。

Instant Run的小瑕疵

雖然Instant Run已經(jīng)足夠聰明,能根據(jù)不同的場景來采用不同的方式構(gòu)建磷蜀,但是有時候代碼修改后雖然采取了熱拔插的方式召耘,但是一些只有在application第一次啟動時初始化的操作并不能影響到,比如下面這個例子褐隆,雖然我們已經(jīng)修改了里面的值污它,但是通過Instant Run啟動的數(shù)據(jù)并沒有變化,這種情況就需要重新啟動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來啟動蜜宪,最好不要直接通過設(shè)備來啟動,可能

更詳細的小技巧清單tips and tricks祥山,這都是Android官方的文檔但是只有少量有價值的東西

  • 調(diào)整你分配給Gradle進程的資源圃验。在 gradle.properties 文件中合理的設(shè)置 jvmargs 參數(shù)會顯著的提高編譯的速度,無論是Instant Run還是全部編譯缝呕。你可以進行試驗并觀察構(gòu)建時間的影響澳窑,就能發(fā)現(xiàn)這個的價值。
  • 因為ART虛擬機從21版本才開始正式啟用供常,在debug調(diào)試的時候?qū)?minSdkVersion 設(shè)為21或者更高會充分發(fā)揮Instant Run的編譯速度摊聋。
  • 牢記改變manifest文件會導(dǎo)致全部的編譯和部署,速度會很慢栈暇,所以麻裁,如果你的構(gòu)建過程會自動的更新manifest的任何部分,比如會自動的改變versionCode和versionName源祈,在debug時最好關(guān)掉這個行為煎源。
  • Instant Run現(xiàn)在只作用于主進程,所以如果你的應(yīng)用使用多進程香缺,熱拔插和溫拔插在其他的進程會退化成冷拔插的操作甚至是整體全部的編譯如果target API在21以下手销。
  • 如果在Windows下開發(fā),Windows Defender Real-Time Protection可能會導(dǎo)致Instant Run掛掉图张,可以通過添加白名單列表的方式來解決锋拖。
  • 截至該文之前,暫時不支持Jack compiler祸轮,Instrumentation Tests兽埃,或者同時部署到多臺設(shè)備上。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末适袜,一起剝皮案震驚了整個濱河市柄错,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌痪蝇,老刑警劉巖鄙陡,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冕房,死亡現(xiàn)場離奇詭異躏啰,居然都是意外死亡,警方通過查閱死者的電腦和手機耙册,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進店門给僵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事帝际÷” “怎么了?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵蹲诀,是天一觀的道長斑粱。 經(jīng)常有香客問我,道長脯爪,這世上最難降的妖魔是什么则北? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮痕慢,結(jié)果婚禮上尚揣,老公的妹妹穿的比我還像新娘。我一直安慰自己掖举,他們只是感情好快骗,可當(dāng)我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著塔次,像睡著了一般方篮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上励负,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天恭取,我揣著相機與錄音,去河邊找鬼熄守。 笑死蜈垮,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的裕照。 我是一名探鬼主播攒发,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼晋南!你這毒婦竟也來了惠猿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤负间,失蹤者是張志新(化名)和其女友劉穎偶妖,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體政溃,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡趾访,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了董虱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扼鞋。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡申鱼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出云头,到底是詐尸還是另有隱情捐友,我是刑警寧澤,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布溃槐,位于F島的核電站匣砖,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏昏滴。R本人自食惡果不足惜脆粥,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望影涉。 院中可真熱鬧变隔,春花似錦、人聲如沸蟹倾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鲜棠。三九已至肌厨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間豁陆,已是汗流浹背柑爸。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留盒音,地道東北人表鳍。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像祥诽,于是被迫代替她去往敵國和親譬圣。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,298評論 25 707
  • afinalAfinal是一個android的ioc雄坪,orm框架 https://github.com/yangf...
    passiontim閱讀 15,437評論 2 45
  • 凌晨一點厘熟。剛回到住的地方,對于一個N年不跑步今天跑了五公里的人來說维哈。已經(jīng)累炸绳姨。 腦子里有很多東西在轉(zhuǎn),好吧阔挠。我承認...
    鯨魚藍閱讀 86評論 0 0
  • 導(dǎo)讀:現(xiàn)在這個社會谒亦,用以前的方法想成功很難了竭宰,如果你學(xué)會了策劃,那么希望很大份招。策劃不是狹義上的切揭,而是廣義上的 。 ...
    飛馳的死兔子閱讀 892評論 0 0
  • 開篇 現(xiàn)在網(wǎng)盤如山倒, 網(wǎng)盤一個一個都開始關(guān)閉了. 是時候做一個自己的個人云儲存了.市面上適合個人用的的 nas ...
    yww閱讀 2,057評論 0 4