Apply Changes 在 Android 11 中的增強(qiáng)特性

image

簡介

Apply Changes 是 Android Studio 中的一項(xiàng)功能,我們?cè)?Android Studio 3.5 中引入了這項(xiàng)功能,以幫助開發(fā)者快速迭代您對(duì)應(yīng)用所做的更改。Apply Changes 通過 JVMTI API 來判斷是否可以使用此方式進(jìn)行變更。在 Android 11 上,ART (Android 運(yùn)行時(shí)) 擴(kuò)展了 JVMTI API,引入了一個(gè)名為 Structural Class Redefinition (類的結(jié)構(gòu)性重定義) 的新功能。該功能使 Apply Changes 在 Android 11 設(shè)備上增加了一類新的應(yīng)用場景。現(xiàn)在,可以使用 Apply Changes 將更復(fù)雜的修改快速部署到正在運(yùn)行的應(yīng)用上,這包括:

  • 增加方法 (Android Studio 4.1)
  • 增加資源文件 (Android Studio 4.2)
  • 增加靜態(tài)字段 (Android Studio 4.2)

這可以使您減少研發(fā)周期,最大化生產(chǎn)效率。本文我們將探討在 Android Studio 中該功能是如何實(shí)現(xiàn)的。

通過 Android Studio 實(shí)現(xiàn)更強(qiáng)的功能

Apply Changes 基于 Android Runtime 特性從頭設(shè)計(jì),所以可以利用其升級(jí)更新的功能不斷發(fā)展。

對(duì)于類的結(jié)構(gòu)性重定義而言,將具有新增方法的類發(fā)送到 ART,這與之前的 Android 版本沒有什么不同。如今新增了一個(gè)入口 API,為此您需要將 Android Studio 升級(jí)到 4.1 或更高版本,以利用動(dòng)態(tài)在運(yùn)行中添加新方法的優(yōu)勢,包括靜態(tài)方法和虛方法。

但是,增加變量需要在 Android Studio 中進(jìn)行新的分析。當(dāng)增加一個(gè)新的變量時(shí),ART 不會(huì)嘗試為其分配具體的值。(請(qǐng)持續(xù)關(guān)注后續(xù)關(guān)于 ART 實(shí)現(xiàn)類的結(jié)構(gòu)性重定義的文章)。取而代之的是,被增加的變量僅會(huì)被初始化為默認(rèn)初始值或 null,并且如何初始化將由 Android Studio 決定。

此過程較為復(fù)雜,考慮這樣一種情況: 將 long 類型靜態(tài)變量 y 添加到類中 (y 的初始化發(fā)生在類加載期間)。例如:

public class example {

   public final static long x = System.currentTimeMillis();
   public final static long y = System.currentTimeMillis();

}

如果該類被加載,x 和 y 的值將會(huì)非常接近。在通過使用 Apply Code Changes 增加 y 的情況下,很難計(jì)算出正確的 y 值。事實(shí)上對(duì) y 的賦值,即使采用最接近的模擬類加載和初始化 y 的程序,也是有爭議的。因?yàn)閮蓚€(gè) curentTimeMillis() 在靜態(tài)初始化 (<clinit> 方法) 中調(diào)用,Apply Changes 將繼續(xù)遵守不重新執(zhí)行 <clinit> 方法任何部分的策略,所以新增的 y 值為 0。

幸運(yùn)的是,Apply Changes 已經(jīng) 使用了 D8 分析 DEX 文件,并且作為該過程的一部分,在最新版本的 Android Studio 中,Apply Changes 能夠利用 D8 新引入的 Inspector API。這種輕量級(jí)的檢查 API 能夠在 DEX 比較過程中計(jì)算出一些額外的信息,而僅需增加少量開銷 (僅檢查發(fā)生修改的 Java 類)。一系列有關(guān)新增變量的元信息將被附加在發(fā)送到對(duì)應(yīng)設(shè)備的 Apply Changes 請(qǐng)求的 ProtoBuf 消息中。

在設(shè)備上,Android Studio 將我們的更改傳達(dá)給 VM 之前,Java Agent 將檢查即將被替換的當(dāng)前加載類。通過比較當(dāng)前加載類和新編譯類的字段,即可計(jì)算出新增字段列表及每個(gè)字段的初始值。然后,代理程序?qū)簳r(shí)掛起所有其他線程,防止未初始化的新增字段在替換前被訪問。如果替換請(qǐng)求成功執(zhí)行,它將使用合適的變量初始化新增字段。

局限與即將推出的新功能

在 Android Studio 4.2 Canary 3 中,此功能僅支持新增靜態(tài)原語的應(yīng)用場景。作為衍生功能,這有助于在 R.class 中新增值,使 Apply Changes 支持新增資源。

對(duì)于所有使用 Apply Changes 的場景中,需要記住一點(diǎn): 當(dāng)您重新編譯并重新運(yùn)行一個(gè)程序,任何語義和之前都是不同的。試想這樣的一個(gè)例子: 構(gòu)造函數(shù)發(fā)生了變化,但是所有基于原來的構(gòu)造函數(shù)初始化的對(duì)象并沒有重新初始化。同樣的,該規(guī)則也適用于靜態(tài)變量,因?yàn)?<clinits> 不會(huì)被重新調(diào)用。

希望 Android Studio 中這一新功能可以為開發(fā)者帶來生產(chǎn)力的提高。我們一如既往地歡迎大家給我們 反饋,并讓我們知道您希望看到哪些改進(jìn)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容