摘要:根據(jù)文件中的各個類,計算出校驗和,并臨時保存在主機(jī)的一個緩存數(shù)據(jù)庫中。通過對比新編譯的文件和之前的文件的校驗和,可以在很短的時間內(nèi)找到更改過的類。這次,它只獲取壓縮文件的,并保守估計相應(yīng)之間可能存在的差異。
深入探討 Android Studio 團(tuán)隊如何構(gòu)建 Instant Run 的后繼者 —— Apply Changes。原文地址:Android Studio Project Marble: Apply Changes
原文作者:Jon Tsao
譯文出自:掘金翻譯計劃
本文永久鏈接:github.com/xitu/gold-m…
譯者:qiuyuezhong
校對者:phxnirvana
Android Studio 團(tuán)隊有一系列深入探討 Project Marble 細(xì)節(jié)和幕后情況的文章,本文是其中的第一篇。從發(fā)布 Android Studio 3.3 開始,Project Marble 就致力于保證 IDE 基本功能的穩(wěn)定性和流暢度。這篇文章是由 Apply Changes 團(tuán)隊的 Jon Tsao(產(chǎn)品經(jīng)理),Esteban de la Canal(技術(shù)負(fù)責(zé)人),F(xiàn)abien Sanglard(工程師)和 Alan Leung(工程師)共同完成。
Android Studio 的一個主要目標(biāo)是為你的 app 提供快速的代碼編輯和驗證工具。當(dāng)我們創(chuàng)建 Instant Run 的時候,我們希望它能夠明顯加速你的開發(fā)流程,但是現(xiàn)在看來它并沒有達(dá)到預(yù)期目標(biāo)。作為 Project Marble 的一部分,我們一直在重新思考 Instant Run,并提出了一個更實用的替代方案 Apply Changes。Apply Changes 作為一個可以加快開發(fā)流程的新方法,最初在 Android Studio 3.5 的 Canary Channel 發(fā)布預(yù)覽。在這篇文章中,我們想深入聊聊它是如何工作的,以及迄今為止我們的工作。
Instant Run通過 Instant Run,我們想解決兩個問題:1)節(jié)省構(gòu)建和部署應(yīng)用程序到設(shè)備上的時間,2)使應(yīng)用程序在不丟失運行狀態(tài)的情況下部署更改。為了在 Instant Run 中做到這一點,我們在構(gòu)建的時候重寫你的 APK 來注入鉤子,以便在運行的時候進(jìn)行類的替換。要更詳細(xì)的了解 Instant Run 背后的架構(gòu),可以參考幾年前 Medium 上的這篇文章。
對于簡單的 app,這個方案一般都表現(xiàn)很好,但是對于更復(fù)雜的 app 來說,它可能會使構(gòu)建時間變長,或者會由于 app 與 Instant Run 構(gòu)建過程之間有沖突而導(dǎo)致令人頭疼的錯誤。隨著這些問題的出現(xiàn),我們在后續(xù)的版本中持續(xù)改進(jìn)提升 Instant Run。但是,我們無法完全解決這些問題,讓它符合我們的期望。
我們后退了一步,決定從頭開始構(gòu)建一個新的架構(gòu),它就是 Apply Changes。和 Instant Run 不同,Apply Changes 不會在構(gòu)建的時候修改你的 APK。取而代之,我們用 Android 8.0(Oreo)上支持的 Runtime Instrumentation 以及更新的設(shè)備和模擬器在運行時重定義類。
Apply Changes對于運行在 Android 8.0 或者更新版本上的設(shè)備和虛擬機(jī),Android Studio 現(xiàn)在有三個按鈕來控制應(yīng)用程序重啟的程度:
Run 會部署所有的改動并重啟應(yīng)用程序。
Apply Changes 會嘗試應(yīng)用資源和代碼的更改,并只重啟 Activity 而不是重啟應(yīng)用程序。
Apply Code Changes 會嘗試應(yīng)用代碼的更改,而不重啟任何東西。
通常只有方法體內(nèi)部的代碼更改才對 Apply Changes 具有兼容性。
原則基于在 Instant Run 上的經(jīng)驗和反饋,我們采用了一些原則來指導(dǎo)我們的架構(gòu)設(shè)計和決策:
將構(gòu)建/部署的速度和狀態(tài)丟失兩者獨立開。我們想將節(jié)省構(gòu)建和部署的時間,與在不丟失運行狀態(tài)的情況下部署更改這兩個目標(biāo)分開。不管是一般的運行或者調(diào)試,或者代碼的熱替換,快速構(gòu)建和部署應(yīng)該是所有部署類型的目標(biāo)。作為構(gòu)建 Apply Changes 的一部分,我們發(fā)現(xiàn)了很多可以優(yōu)化構(gòu)建和部署速度的領(lǐng)域,在后面的文章中,我們會詳細(xì)介紹它們。
穩(wěn)定性至關(guān)重要。即便在 100 次中這個功能以極快的速度運行了 99 次,如果你的 app 因為這個功能而崩潰了一次,并且你花半個小時來嘗試找出原因,那么其他 99 次獲得的收益也就全部被抵消了。由于我們堅持這一原則,Apply Changes 不會像 Instant Run 那樣在構(gòu)建期間修改你的 APK。帶來的副作用是,在我們進(jìn)行穩(wěn)定性優(yōu)化的早期版本中,Apply Changes 會比 Instant Run 的平均速度稍慢,但是我們將繼續(xù)提高構(gòu)建和部署的速度。
透明。Instant Run 按鈕會自動決定是否在必要時重啟你的 app 或者 Activity,對于這樣不可預(yù)測性和行為不一致性的反饋,我們也考慮了進(jìn)來。我們希望在任何時候你都能清楚透明的了解 Apply Changes 要做什么,如果你的代碼有不兼容的修改會發(fā)生什么。因此如果有檢測到與 Apply Changes 不兼容的修改,我們現(xiàn)在會明確提示你。
我們來深入研究下 Apply Changes 是如何工作的。在你修改 app 之后,當(dāng)前設(shè)備上已經(jīng)安裝或正在運行的應(yīng)用程序和 Android Studio 剛剛編譯出來的應(yīng)用程序是有差異的,Apply Changes 需要弄清楚如何應(yīng)用這些差異。這個過程可以分成兩個步驟:1)弄清楚差異是什么,2)將差異發(fā)送到設(shè)備上并應(yīng)用它。
為了快速確定差異,Apply Changes 沒有從設(shè)備抓取完整的 APK,而是向設(shè)備發(fā)送一個快速的請求,去拉取已經(jīng)安裝 APK 的對應(yīng)目錄和簽名。將這兩部分信息和新 APK 進(jìn)行比較,Apply Changes 可以高效地找出自上次部署以來修改過的文件列表,而不需要檢查 APK 的所有內(nèi)容。需要注意的是,這個算法并不依賴于構(gòu)建系統(tǒng),因為差異并不是與上一次構(gòu)建相比較得到的,而是與安裝到設(shè)備上的 APK 比較得來。由于 Apply Changes 只針對 APK 之間的差異進(jìn)行操作,因此它并不要求 Gradle 插件版本和 Gradle 同步。這樣,Apply Changes 可以運行于所有的構(gòu)建系統(tǒng)上。
在生成更改過的文件列表之后,根據(jù)所更改的內(nèi)容,需要執(zhí)行不同的操作來將這些更改應(yīng)用到正在運行的 app 上,這也決定了要使這些更改生效,app 需要重啟到什么程度:
更改 resource/asset 文件。 這種情況下會重新安裝應(yīng)用程序,但只會重啟 Activity,并獲取修改后的資源。只有修改過的資源才會被發(fā)送到設(shè)備上。
更改 .dex 文件。 Android 8.0 的 Android Runtime 提供了替換已加載類的字節(jié)碼的能力,只要新的字節(jié)碼不會改變內(nèi)存中現(xiàn)有對象的布局。這意味著要想兼容 Apply Changes,更改的代碼會有一些限制:方法名,類名,和簽名都不能更改,它們的成員變量也不能更改。
但這個機(jī)制不能在 .dex 級別,只能在類級別工作。否則,如果 .dex 文件包含成千上萬個類,即便只有一個類更改了,也需要對所有類進(jìn)行替換,這樣效率太低。對于 .dex 文件,我們比較它的內(nèi)容來找出更改過的類,只替換掉它們。如果替換成功(例如,類的布局沒有改變),為了避免正在運行和已安裝的 app 的版本不一致,會在后臺安裝 app。
更改 .dex 文件和資源文件。 這個情況是上面兩種情況的組合。先處理代碼的部分,如果成功了,會和新的資源一起安裝。為了加載新的資源,主 Activity 會被重啟。這是一個全做或全不做的操作,如果代碼的改變不能成功地應(yīng)用,正在運行的 app 什么都不會改變。
更改其他東西。 這是最糟的情況,比如 AndroidManifest.xml 或者 native .so 這些文件被更改了。在這種情況下,是不可能不重啟應(yīng)用程序來應(yīng)用更改的?!癆pply Changes” 和 “Apply Code Changes”這兩個操作都不會試圖去部署它,它們會告訴用戶應(yīng)用程序需要重啟。
關(guān)于架構(gòu)的更多詳細(xì)信息,請收聽 Android Developers Backstage 播客的最新一集,技術(shù)負(fù)責(zé)人 Esteban de la Canal 對 Apply Changes 進(jìn)行了深入探討。
比較 .dex 文件前一個部分解釋了 Apply Changes 需要比較并確認(rèn)在設(shè)備上更改(修改/添加/刪除)了哪個具體的類。為了不增加從設(shè)備獲取大量內(nèi)容的開銷,它在后臺使用了 D8 的 DEX 文件分析能力來檢查 Android Studio 部署到設(shè)備上的每個 .dex 文件的內(nèi)容。根據(jù) .dex 文件中的各個類,計算出校驗和,并臨時保存在主機(jī)的一個緩存數(shù)據(jù)庫中。通過對比新編譯的 .dex 文件和之前的 .dex 文件的校驗和,Apply Changes 可以在很短的時間內(nèi)找到更改過的類。
Delta push如上所述,只有更改了的文件才會被發(fā)送到設(shè)備上,我們稱之為 “ delta push”。與上面提到的 DEX 文件對比類似,Apply Changes 計算已安裝的 APK 和最近構(gòu)建的 APK 之間的差異,而不需要從設(shè)備獲取所有內(nèi)容。這次,它只獲取壓縮文件的 Central Directory,并保守估計相應(yīng) APK 之間可能存在的差異。通過只傳輸已經(jīng)改變的部分,Android Studio 傳輸?shù)臄?shù)據(jù)比完整的 APK 上傳要少很多。在大多數(shù)情況下,總傳輸數(shù)據(jù)從幾 MiB 減少到幾 KiB。
接下來現(xiàn)在可以在 Android Studio 3.5 的 Canary release channel 中使用 Apply Changes。我們歡迎下載最新的 Android Studio,將 Apply Changes 使用到你的項目中,并向我們提出早期的反饋。作為提醒,你可以同時運行 Android Studio 的穩(wěn)定版本和 canary release 版本 。如果你在使用 Apply Changes 時遇到任何問題,請?zhí)峤灰粋€ bug 并附上對應(yīng)的 idea.log 文件。我們會持續(xù)優(yōu)化部署性能,修復(fù) bug,并聽取你的建議和反饋。
如果發(fā)現(xiàn)譯文存在錯誤或其他需要改進(jìn)的地方,歡迎到 掘金翻譯計劃 對譯文進(jìn)行修改并 PR,也可獲得相應(yīng)獎勵積分。文章開頭的 本文永久鏈接 即為本文在 GitHub 上的 MarkDown 鏈接。
掘金翻譯計劃 是一個翻譯優(yōu)質(zhì)互聯(lián)網(wǎng)技術(shù)文章的社區(qū),文章來源為 掘金 上的英文分享文章。內(nèi)容覆蓋 Android、iOS、前端、后端、區(qū)塊鏈、產(chǎn)品、設(shè)計、人工智能等領(lǐng)域,想要查看更多優(yōu)質(zhì)譯文請持續(xù)關(guān)注 掘金翻譯計劃、官方微博、知乎專欄。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/7377.html
摘要:它是對的重大改進(jìn)和全面替代方案。一個更直接的方法是開始遷移,并且檢查可能出現(xiàn)的報錯。遷移工具位于菜單欄的選項。這個選項將遷移整個項目的所有模塊。中的遷移工具是遷移的主要方式。遷移應(yīng)用變更最少的代碼以保證應(yīng)用可以仍能正常運行。 原文地址:Cross-stitching Plaid and AndroidX 原文作者:Tiem Song 譯文出自:掘金翻譯計劃 本文永久鏈接:github.co...
閱讀 2820·2021-10-11 10:57
閱讀 2417·2021-08-27 16:20
閱讀 1395·2019-08-30 13:03
閱讀 1573·2019-08-30 12:50
閱讀 3352·2019-08-29 14:16
閱讀 1569·2019-08-29 11:12
閱讀 1622·2019-08-28 17:53
閱讀 2903·2019-08-27 10:58