你真的瞭解Instant Run嗎?

今天是週二,又輪到我寫文章了。


先扯點題外話,我是2010年8月份開始自學Android的,到現在已經快有6年的時間了。當時爲了自學我專門買了一本書,叫《Android高級編程》,作者是Reto Meier,這本書現在仍然還在我的書架上,這是我剛拍的一張略顯陳舊的照片:




然後最近在學習Instant Run,看了下Android的官方視頻,我意外地發現,這位幫助我入門的帥哥竟然已經加入Google了。




現在我就想知道《第一行代碼》的作者何時可以加入Google?^_^


扯蛋就先扯到這裏,我們來進入今天的正題。


什麼是Instant Run?


我們都知道,Android Studio功能非常強大,在各個功能性方面都要優於Eclipse,唯獨在速度方面被吐糟得比較慘。Android Studio團隊爲此也是做了很多的優化,在Android Studio 2.0中,對速度方面進行了大幅度的改進:



可以看到,Android Studio 2.0中編譯和部署的速度都有了很大程度的提升,但唯獨安裝速度沒有得到提升,這很正常嘛,畢竟應用程序的安裝快慢是由我們手機的硬件配置來決定的,和開發工具有什麼關係呢。


但是Android Studio團隊並不滿足於此,他們想將速度提升到極致,於是在Android Studio 2.0中加入了Instant Run功能。當然,只要你的Android Studio版本在2.0以上,你不需要進行任何學習就可以使用Instant Run,但是如果懂得了它背後的原理,你將可以使用得更好。


傳統情況下,我們修改程序後重新運行一次程序需要經歷 代碼重新編譯 -> 停止程序 -> 重新安裝 -> 重新啓動 這樣一個過程,而Instant Run則嘗試只將程序變更的部分部署到手機上,儘量避免重新安裝或重新啓動程序,以此大大提升調試程序的效率。


當我們第一次運行程序之後,Android Studio中的運行按鈕會變成這個樣子:



可以看到,運行的三角形旁邊多了一個閃電符號,這就說明現在可以使用Instant Run了。


Instant Run主要分爲三種類型,hot swap、warm swap和cold swap,Android Studio會根據代碼的修改情況自動選擇使用哪種swap類型,下面我們就來針對這三種swap類型詳細地學習一下。


Hot Swap


hot swap是所有swap方式中效率最高的一種,應用程序不需要重新安裝,也不需要重啓就可以完成程序變更。但是hot swap不會對程序中的對象進行重新初始化,也就是說可能某些場景下需要重啓Activity才能看出具體的變更內容。Android Studio對於hot swap這種情況默認是重啓Activity的,當然你也可以到設置中去改變這一默認行爲,具體路徑是 Settings -> Build, Execution, Deployment -> Instant Run -> Restart activity on code changes。


hot swap的適用條件比較少,只有一種情況會被Android Studio視爲hot swap類型,就是修改一個現有方法中的代碼,效果如下圖所示:



可以看到,我只改動了一個現有方法的內部代碼,重新運行後編譯和部署的速度都非常快,最關鍵的是,應用程序並沒有重新安裝或重啓,甚至於Activity都沒有重啓(由於我進行了上述的設置),然後修改的代碼就成功替換了。


Warm Swap


warm swap也非常快,這種swap類型同樣不需要重新安裝或重啓程序就可以完成程序變更,但是warm swap要求必須重啓Activity。你會在界面上看到屏幕很快地閃一下,同時Activity的生命週期會重新執行。


warm swap的適用條件也比較侷限,只有一種情況會被Android Studio視爲warm swap類型,就是修改或刪除一個現有的資源文件,效果如下圖所示:




可以看到,我改動了佈局文件中的內容,重新運行後速度仍然很快,應用程序並沒有重新安裝或重啓,只是Activity重啓了一下,因爲要將修改後的佈局內容展示到界面上。


Cold Swap


cold swap相對而言就要更慢一些了,Android Studio會自動記錄我們項目的每次修改,然後將修改的這部分內容打成一個dex文件發送到手機上,儘管這種swap類型仍然不需要去安裝一個全新的APK,但是爲了加載這個新的dex文件,整個應用程序必須進行重啓才行。另外,cold swap的工作原理是基於multidex機制來實現的,在不引入外部library的情況下,只有5.0及以上的設備才支持multidex,因此,如果你使用了5.0以下的設備,那麼cold swap就無法工作了,這種情況會執行最原始的完整APK安裝過程。


cold swap的適用條件非常多,下面我列出一個詳細的清單,有哪些情況會被Android Studio視爲cold swap類型:


  • 添加、刪除或修改一個註解

  • 添加、刪除或修改一個字段

  • 添加、刪除或修改一個方法

  • 添加一個類

  • 修改一個類的繼承結構

  • 修改一個類的接口實現

  • 修改一個類的static修飾符

  • 涉及資源文件id的改動


那麼我們還是來看一下演示效果吧,如下圖所示:



可以看到,這裏我給第二個Button添加了一個新的點擊事件方法,添加一個方法是滿足cold swap條件的,那麼我們明顯可以看出,應用程序重新啓動了,但是整體的速度依然很快,整個重新運行的過程在5秒種之內完成的,我的截圖都是實時速度,沒有進行加速播放。


Full APK


除了滿足以上條件的其他程序變更,Instant Run目前都還不支持,主要包括以下一些情況:


  • 改變AndroidManifest.xml文件的內容

  • 改變被AndroidManifest.xml文件所引用的資源,比如string.xml中的app_name

  • 改變桌面widget的UI相關元素


當程序變更不被Instant Run所支持時,就會執行完整的APK安裝過程,同時Android Studio會給出這樣的提示:




由於這種情況重新運行時間比較長,就不給大家截圖演示了,以前我們使用低於2.0版本的Android Studio開發時,每次都是執行的這種情況。


當然,這只是目前的Instant Run規則,Android Studio團隊還會一直進行優化,增加hot swap和warm swap的條件,減少cold swap和full apk的條件,相信未來的Android Studio會更加好用。


Rerun


儘管Instant Run儘可能地想要變得更智能,但是它也沒有時光倒流的能力。比如hot swap或者warm swap是根本不會重啓程序的,而如果你修改了一些只有在程序啓動的時候纔會初始化的代碼,那麼Instant Run對此也是無能爲力的,因爲修改的代碼根本就沒有執行到。


針對這種情況,Android Studio專門提供了一個Rerun按鈕:




中間那個按鈕就是Rerun按鈕,使用這個按鈕來重新運行程序,應用程序會被強制重啓,從而初始化的一些代碼就能夠執行到了。Android Studio無法得知改動的代碼是不是在程序初始化的時候才執行的,而我們卻可以知道,所以確保你理解了Rerun這個按鈕的作用,並在恰當的時機使用它。


補充


hot swap由於其工作原理的限制還有一些特殊問題。hot swap會在應用程序的內部開啓一個服務器,然後由Android Studio自動計算出方法內實現的變更,將變更代碼發送到服務器,服務器再利用類加載器和委託機制將新的代碼實現注入到現有應用程序中,從而完成替換工作。


但是整個過程中,新的代碼實現並沒有被保存到本地,也就是說一旦設備和Android Studio的連接斷掉了(比如拔掉數據線),我們使用hot swap替換的代碼也就隨之不見了。當你再次打開程序的時候,你會看到這樣的提示:




看到這個提示並不用感到驚奇,這就說明你的hot swap代碼失效了,現在的程序仍然使用的老的代碼。遇到這種情況只需要將手機連上電腦,然後在Android Studio中重新運行一下程序就可以解決了。另外只有在debug模式下才可能會出現這個提示,release模式下是不可能出現的,所以不用擔心這個提示會讓用戶感到困惑。




如果你有好的技術文章想和大家分享,歡迎向我的公衆號投稿,投稿具體細節請在公衆號主頁點擊“投稿”菜單查看。


歡迎長按下圖 -> 識別圖中二維碼或者掃一掃關注我的公衆號:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章