我們都知道,Android Studio功能非常強(qiáng)大,在各個(gè)功能性方面都要優(yōu)于Eclipse,唯獨(dú)在速度方面被吐糟得比較慘。Android Studio團(tuán)隊(duì)為此也是做了很多的優(yōu)化,在Android Studio 2.0中,對(duì)速度方面進(jìn)行了大幅度的改進(jìn):
可以看到,Android Studio 2.0中編譯和部署的速度都有了很大程度的提升,但唯獨(dú)安裝速度沒(méi)有得到提升,這很正常嘛,畢竟應(yīng)用程序的安裝快慢是由我們手機(jī)的硬件配置來(lái)決定的,和開(kāi)發(fā)工具有什么關(guān)系呢。
但是Android Studio團(tuán)隊(duì)并不滿足于此,他們想將速度提升到極致,于是在Android Studio 2.0中加入了Instant Run功能。當(dāng)然,只要你的Android Studio版本在2.0以上,你不需要進(jìn)行任何學(xué)習(xí)就可以使用Instant Run,但是如果懂得了它背后的原理,你將可以使用得更好。
傳統(tǒng)情況下,我們修改程序后重新運(yùn)行一次程序需要經(jīng)歷 代碼重新編譯 -> 停止程序 -> 重新安裝 -> 重新啟動(dòng) 這樣一個(gè)過(guò)程,而Instant Run則嘗試只將程序變更的部分部署到手機(jī)上,盡量避免重新安裝或重新啟動(dòng)程序,以此大大提升調(diào)試程序的效率。
當(dāng)我們第一次運(yùn)行程序之后,Android Studio中的運(yùn)行按鈕會(huì)變成這個(gè)樣子:
可以看到,運(yùn)行的三角形旁邊多了一個(gè)閃電符號(hào),這就說(shuō)明現(xiàn)在可以使用Instant Run了。
Instant Run主要分為三種類(lèi)型,hot swap、warm swap和cold swap,Android Studio會(huì)根據(jù)代碼的修改情況自動(dòng)選擇使用哪種swap類(lèi)型,下面我們就來(lái)針對(duì)這三種swap類(lèi)型詳細(xì)地學(xué)習(xí)一下。
hot swap是所有swap方式中效率最高的一種,應(yīng)用程序不需要重新安裝,也不需要重啟就可以完成程序變更。但是hot swap不會(huì)對(duì)程序中的對(duì)象進(jìn)行重新初始化,也就是說(shuō)可能某些場(chǎng)景下需要重啟Activity才能看出具體的變更內(nèi)容。Android Studio對(duì)于hot swap這種情況默認(rèn)是重啟Activity的,當(dāng)然你也可以到設(shè)置中去改變這一默認(rèn)行為,具體路徑是 Settings -> Build, Execution, Deployment -> Instant Run -> Restart activity on code changes。
hot swap的適用條件比較少,只有一種情況會(huì)被Android Studio視為hot swap類(lèi)型,就是修改一個(gè)現(xiàn)有方法中的代碼,效果如下圖所示:
可以看到,我只改動(dòng)了一個(gè)現(xiàn)有方法的內(nèi)部代碼,重新運(yùn)行后編譯和部署的速度都非常快,最關(guān)鍵的是,應(yīng)用程序并沒(méi)有重新安裝或重啟,甚至于Activity都沒(méi)有重啟(由于我進(jìn)行了上述的設(shè)置),然后修改的代碼就成功替換了。
warm swap也非常快,這種swap類(lèi)型同樣不需要重新安裝或重啟程序就可以完成程序變更,但是warm swap要求必須重啟Activity。你會(huì)在界面上看到屏幕很快地閃一下,同時(shí)Activity的生命周期會(huì)重新執(zhí)行。
warm swap的適用條件也比較局限,只有一種情況會(huì)被Android Studio視為warm swap類(lèi)型,就是修改或刪除一個(gè)現(xiàn)有的資源文件,效果如下圖所示:
可以看到,我改動(dòng)了布局文件中的內(nèi)容,重新運(yùn)行后速度仍然很快,應(yīng)用程序并沒(méi)有重新安裝或重啟,只是Activity重啟了一下,因?yàn)橐獙⑿薷暮蟮牟季謨?nèi)容展示到界面上。
cold swap相對(duì)而言就要更慢一些了,Android Studio會(huì)自動(dòng)記錄我們項(xiàng)目的每次修改,然后將修改的這部分內(nèi)容打成一個(gè)dex文件發(fā)送到手機(jī)上,盡管這種swap類(lèi)型仍然不需要去安裝一個(gè)全新的APK,但是為了加載這個(gè)新的dex文件,整個(gè)應(yīng)用程序必須進(jìn)行重啟才行。另外,cold swap的工作原理是基于multidex機(jī)制來(lái)實(shí)現(xiàn)的,在不引入外部library的情況下,只有5.0及以上的設(shè)備才支持multidex,因此,如果你使用了5.0以下的設(shè)備,那么cold swap就無(wú)法工作了,這種情況會(huì)執(zhí)行最原始的完整APK安裝過(guò)程。
cold swap的適用條件非常多,下面我列出一個(gè)詳細(xì)的清單,有哪些情況會(huì)被Android Studio視為cold swap類(lèi)型:
添加、刪除或修改一個(gè)注解
添加、刪除或修改一個(gè)字段
添加、刪除或修改一個(gè)方法
添加一個(gè)類(lèi)
修改一個(gè)類(lèi)的繼承結(jié)構(gòu)
修改一個(gè)類(lèi)的接口實(shí)現(xiàn)
修改一個(gè)類(lèi)的static修飾符
涉及資源文件id的改動(dòng)
那么我們還是來(lái)看一下演示效果吧,如下圖所示:
可以看到,這里我給第二個(gè)Button添加了一個(gè)新的點(diǎn)擊事件方法,添加一個(gè)方法是滿足cold swap條件的,那么我們明顯可以看出,應(yīng)用程序重新啟動(dòng)了,但是整體的速度依然很快,整個(gè)重新運(yùn)行的過(guò)程在5秒種之內(nèi)完成的,我的截圖都是實(shí)時(shí)速度,沒(méi)有進(jìn)行加速播放。
除了滿足以上條件的其他程序變更,Instant Run目前都還不支持,主要包括以下一些情況:
改變AndroidManifest.xml文件的內(nèi)容
改變被AndroidManifest.xml文件所引用的資源,比如string.xml中的app_name
改變桌面widget的UI相關(guān)元素
當(dāng)程序變更不被Instant Run所支持時(shí),就會(huì)執(zhí)行完整的APK安裝過(guò)程,同時(shí)Android Studio會(huì)給出這樣的提示:
由于這種情況重新運(yùn)行時(shí)間比較長(zhǎng),就不給大家截圖演示了,以前我們使用低于2.0版本的Android Studio開(kāi)發(fā)時(shí),每次都是執(zhí)行的這種情況。
當(dāng)然,這只是目前的Instant Run規(guī)則,Android Studio團(tuán)隊(duì)還會(huì)一直進(jìn)行優(yōu)化,增加hot swap和warm swap的條件,減少cold swap和full apk的條件,相信未來(lái)的Android Studio會(huì)更加好用。
盡管Instant Run盡可能地想要變得更智能,但是它也沒(méi)有時(shí)光倒流的能力。比如hot swap或者warm swap是根本不會(huì)重啟程序的,而如果你修改了一些只有在程序啟動(dòng)的時(shí)候才會(huì)初始化的代碼,那么Instant Run對(duì)此也是無(wú)能為力的,因?yàn)樾薷牡拇a根本就沒(méi)有執(zhí)行到。
針對(duì)這種情況,Android Studio專(zhuān)門(mén)提供了一個(gè)Rerun按鈕:
中間那個(gè)按鈕就是Rerun按鈕,使用這個(gè)按鈕來(lái)重新運(yùn)行程序,應(yīng)用程序會(huì)被強(qiáng)制重啟,從而初始化的一些代碼就能夠執(zhí)行到了。Android Studio無(wú)法得知改動(dòng)的代碼是不是在程序初始化的時(shí)候才執(zhí)行的,而我們卻可以知道,所以確保你理解了Rerun這個(gè)按鈕的作用,并在恰當(dāng)?shù)臅r(shí)機(jī)使用它。
hot swap由于其工作原理的限制還有一些特殊問(wèn)題。hot swap會(huì)在應(yīng)用程序的內(nèi)部開(kāi)啟一個(gè)服務(wù)器,然后由Android Studio自動(dòng)計(jì)算出方法內(nèi)實(shí)現(xiàn)的變更,將變更代碼發(fā)送到服務(wù)器,服務(wù)器再利用類(lèi)加載器和委托機(jī)制將新的代碼實(shí)現(xiàn)注入到現(xiàn)有應(yīng)用程序中,從而完成替換工作。
但是整個(gè)過(guò)程中,新的代碼實(shí)現(xiàn)并沒(méi)有被保存到本地,也就是說(shuō)一旦設(shè)備和Android Studio的連接斷掉了(比如拔掉數(shù)據(jù)線),我們使用hot swap替換的代碼也就隨之不見(jiàn)了。當(dāng)你再次打開(kāi)程序的時(shí)候,你會(huì)看到這樣的提示:
看到這個(gè)提示并不用感到驚奇,這就說(shuō)明你的hot swap代碼失效了,現(xiàn)在的程序仍然使用的老的代碼。遇到這種情況只需要將手機(jī)連上電腦,然后在Android Studio中重新運(yùn)行一下程序就可以解決了。另外只有在debug模式下才可能會(huì)出現(xiàn)這個(gè)提示,release模式下是不可能出現(xiàn)的,所以不用擔(dān)心這個(gè)提示會(huì)讓用戶感到困惑。