前言
在Android應(yīng)用開發(fā)中,熱修復(fù)技術(shù)被越來越多的開發(fā)者所使用祈惶,也出現(xiàn)了很多熱修復(fù)框架雕旨,比如:AndFix、Tinker捧请、Dexposed和Nuwa等等凡涩。如果只是會這些熱修復(fù)框架的使用那意義并不大,我們還需要了解它們的原理疹蛉,這樣不管熱修復(fù)框架如何變化活箕,只要基本原理不變,我們就可以很快的掌握它們氧吐。這一個系列不會對某些熱修復(fù)框架源碼進(jìn)行解析讹蘑,而是講解熱修復(fù)框架的通用原理。
1.熱修復(fù)的產(chǎn)生概述
在開發(fā)中我們會遇到如下的情況: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1.剛發(fā)布的版本出現(xiàn)了嚴(yán)重的bug筑舅,這就需要去解決bug座慰、測試并打渠道包在各個應(yīng)用市場上重新發(fā)布,這會耗費大量的人力物力翠拣,代價會比較大版仔。 ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 2.已經(jīng)改正了此前發(fā)布版本的bug,如果下一個版本是一個大版本误墓,那么兩個版本的間隔時間會很長蛮粮,這樣要等到下個大版本發(fā)布再修復(fù)bug,這樣此前版本的bug會長期的影響用戶谜慌。 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
????????3.版本升級率不高然想,并且需要很長時間來完成版本覆蓋,此前版本的bug就會一直影響不升級版本的用戶欣范。
????????4.有一個小而重要的功能变泄,需要短時間內(nèi)完成版本覆蓋,比如節(jié)日活動恼琼。
為了解決上面的問題妨蛹,熱修復(fù)框架就產(chǎn)生了。對于Bug的處理晴竞,開發(fā)人員不要過于依賴熱修復(fù)框架蛙卤,在開發(fā)的過程中還是要按照標(biāo)準(zhǔn)的流程做好自測、配合測試人員完成測試流程(因為沒有一種框架是完美的,它們也只是適應(yīng)大部分情況與使用的情況颤难,它們也是有局限性的)神年。
2.熱修復(fù)框架的對比
熱修復(fù)框架的種類繁多,按照公司團(tuán)隊劃分主要有以下幾種:
類別成員:
????????????????阿里系????????????????AndFix行嗤、Dexposed瘤袖、阿里百川、Sophix
????????????????騰訊系????????????????微信的Tinker昂验、QQ空間的超級補(bǔ)丁、手機(jī)QQ的QFix
????????????????知名公司????????????美團(tuán)的Robust艾扮、餓了么的Amigo既琴、美麗說蘑菇街的Aceso
????????????????其他????????????????????RocooFix、Nuwa泡嘴、AnoleFix
雖然熱修復(fù)框架很多甫恩,但熱修復(fù)框架的核心技術(shù)主要有三類,分別是代碼修復(fù)酌予、資源修復(fù)和動態(tài)鏈接庫修復(fù)磺箕,其中每個核心技術(shù)又有很多不同的技術(shù)方案,每個技術(shù)方案又有不同的實現(xiàn)抛虫,另外這些熱修復(fù)框架仍在不斷的更新迭代中松靡,可見熱修復(fù)框架的技術(shù)實現(xiàn)是繁多可變的。作為開發(fā)需需要了解這些技術(shù)方案的基本原理建椰,這樣就可以以不變應(yīng)萬變雕欺。
部分熱修復(fù)框架的對比如下表所示。
特性? ? ? ? ? ?AndFix? ? ?Tinker/Amigo? ? ?QQ空間????????Robust/Aceso? ? ? ?????Sophix?
即時生效? ? ? ? ? ? 是? ? ? ? ? ? 否? ? ? ? ? ? ? ? ? ? 否????????????????????????是? ? ? ? ? ? ? ?視情況而定
方法替換? ? ? ? ? ? 是? ? ? ? ? ? 是? ? ? ? ? ? ? ? ? ? 是????????????????????????是? ? ? ? ? ? ? ? 是? ? ? ?
類替換? ? ? ? ? ? ? ? 否? ? ? ? ? ? 是? ? ? ? ? ? ? ? ? ? 是????????????????????????否? ? ? ? ? ? ? ? 是
類結(jié)構(gòu)修改? ? ? ? 否? ? ? ? ? ? 是? ? ? ? ? ? ? ? ? ? ?否????????????????????????否? ? ? ? ? ? ? ? 是
資源替換? ? ? ? ? ? 否? ? ? ? ? ? 是? ? ? ? ? ? ? ? ? ? ?是????????????????????????否? ? ? ? ? ? ? ? 是
so替換? ? ? ? ? ? ? ? 否? ? ? ? ? ? 是? ? ? ? ? ? ? ? ? ? ?否????????????????????????否? ? ? ? ? ? ? ? 是
支持gradle? ? ? ? ? 否? ? ? ? ? ?是? ? ? ? ? ? ? ? ? ? ?否????????????????????????否? ? ? ? ? ? ? ? 是
支持ART? ? ? ? ? ? ?是? ? ? ? ? ? 是? ? ? ? ? ? ? ? ? ? 是 ? ? ? ? ? ? ? ? ? ? ? 是? ? ? ? ? ? ? ? 是
支持Android7.0? 是? ? ? ? ? ? 是? ? ? ? ? ? ? ? ? ? 是 ? ? ? ? ? ? ? ? ? ? ? ?是? ? ? ? ? ? ? ?是
我們可以根據(jù)上表和具體業(yè)務(wù)來選擇合適的熱修復(fù)框架棉姐,當(dāng)然上表的信息很難做到完全準(zhǔn)確屠列,因為部分的熱修復(fù)框架還在不斷更新迭代。
從表中也可以發(fā)現(xiàn)Tinker和Amigo擁有的特性最多伞矩,是不是就選它們呢笛洛?也不盡然,擁有的特性多也意味著框架的代碼量龐大乃坤,我們需要根據(jù)業(yè)務(wù)來選擇最合適的苛让,假設(shè)我們只是要用到方法替換,那么使用Tinker和Amigo顯然是大材小用了侥袜。另外如果項目需要即時生效蝌诡,那么使用Tinker和Amigo是無法滿足需求的。對于即時生效枫吧,AndFix浦旱、Robust和Aceso都滿足這一點,這是因為AndFix的代碼修復(fù)采用了底層替換方案九杂,而Robust和Aceso的代碼修復(fù)借鑒了Instant Run原理颁湖,現(xiàn)在我們就來學(xué)習(xí)代碼修復(fù)宣蠕。
3.熱修復(fù)框原理
目前代碼修復(fù)主要有三種原理:底層替換方案,類加載方案甥捺,Instant Run方案抢蚀。
方案 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?????????????????????????????框架
底層替換? ??? ??? ??? ??? ??? ??? ??? ? AndFix、Dexposed镰禾、阿里百川皿曲、Sophix
類加載? ??? ??? ??? ??? ??? ??? ??? ??? ??微信的Tinker、QQZone吴侦、QFix屋休、Amigo、Nuwa
Instant Run? ??? ??? ??? ??? ??? ??? ?Robust备韧、Aceso
我們可以從上表發(fā)現(xiàn)劫樟,各個框架主要是使用什么原理實現(xiàn)。
底層替換原理:
? ? ? ? 底層替換就是直接通過Native層類實現(xiàn)即時的更新织堂,但是由于是在Native層類原有上更改叠艳,所以有很多修改的限制,比如不能增減方法易阳、字段附较,只能修改方法內(nèi)的結(jié)果內(nèi)容,過程如下圖闽烙。
底層替換方案和反射的原理有些關(guān)聯(lián)翅睛,ArtMethod結(jié)構(gòu)體就是反射invoke()方法Native中的調(diào)用,AndFix采用的是替換ArtMethod結(jié)構(gòu)體中的字段黑竞,這樣會有兼容問題捕发,因為廠商可能會修改ArtMethod結(jié)構(gòu)體,導(dǎo)致方法替換失敗很魂。Sophix采用的是替換整個ArtMethod結(jié)構(gòu)體扎酷,這樣不會存在兼容問題。遏匆。
類加載原理:? ??
? ??? ? 類加載就是通過Dex分包方案法挨,通過雙親委托模式進(jìn)行優(yōu)先加載方式實現(xiàn)類的替換。
類加載方案需要重啟App后讓ClassLoader重新加載新的類幅聘,為什么需要重啟呢凡纳?這是因為類是無法被卸載的,因此要想重新加載新的類就需要重啟App帝蒿,因此采用類加載方案的熱修復(fù)框架是不能即時生效的荐糜。
Instant Run原理:
除了資源修復(fù),代碼修復(fù)同樣也可以借鑒Instant Run的原理, 可以說Instant Run的出現(xiàn)推動了熱修復(fù)框架的發(fā)展暴氏。
Instant Run在第一次構(gòu)建apk時延塑,使用ASM在每一個方法中注入了類似如下的代碼:
IncrementalChange localIncrementalChange = $change;//1if(localIncrementalChange !=null) {//2 localIncrementalChange.access$dispatch("onCreate.(Landroid/os/Bundle;)V",newObject[] {this, paramBundle });return; }
其中注釋1處是一個成員變量localIncrementalChange ,它的值為$change答渔,$change實現(xiàn)了IncrementalChange這個抽象接口关带。當(dāng)我們點擊InstantRun時,如果方法沒有變化則$change為null沼撕,就調(diào)用return宋雏,不做任何處理。如果方法有變化务豺,就生成替換類好芭,這里我們假設(shè)MainActivity的onCreate方法做了修改,就會生成替換類MainActivity$override冲呢,這個類實現(xiàn)了IncrementalChange接口,同時也會生成一個AppPatchesLoaderImpl類招狸,這個類的getPatchedClasses方法會返回被修改的類的列表(里面包含了MainActivity)敬拓,根據(jù)列表會將MainActivity的$change設(shè)置為MainActivity$override,因此滿足了注釋2的條件裙戏,會執(zhí)行MainActivity$override的access$dispatch方法乘凸,access$dispatch方法中會根據(jù)參數(shù)”onCreate.(Landroid/os/Bundle;)V”執(zhí)行MainActivity$override的onCreate方法,從而實現(xiàn)了onCreate方法的修改累榜。
借鑒Instant Run的原理的熱修復(fù)框架有Robust和Aceso营勤。
總結(jié):
? ? ? ? 到這里,我們大概理解了三大熱修復(fù)大概的原理壹罚,下一章我會解讀各個框架中的局限性葛作,上文也提到?jīng)]有一個框架是完美的,所以我們要更好的去理解他們處在怎么樣的局限性猖凛,以便我們在使用過程中避免不必要的的時間成本赂蠢。
Android熱修復(fù)原理(一)熱修復(fù)框架對比和代碼修復(fù)