Author:kaedeaandroid
GitHub:android-dynamical-loadinggit
如今網絡上有許多關於動態加載的介紹的文章,談及的關鍵詞彙有動態加載、插件化、熱部署、熱修復等,對於一些剛接觸這方面開發技術的人來講,可能容易混淆。github
雖然我在動態加載系列的文章中或多或少有談到這些概念的區別,可是我以爲認識這些區別對於使用動態加載技術仍是挺重要的,因此特別開這個新的文章進行分析。網絡
不管是插件化、熱部署仍是熱修復,這些技術的根源均可是說是動態加載,這也是我把「動態加載」做爲這個系列文章主題的緣由。框架
動態加載,就是在程序運行時,加載外部的可執行文件並運行。這裏的運行時就是指應用冷啓動並開始工做後;外部能夠是能夠是SD卡,能夠是data目錄,也能夠是jniLib目錄,這些可執行文件是沒有隨着應用一塊兒編譯的。異步
Android的動態加載按照工做機制的不一樣,能夠分爲虛擬機層動態加載和Native層動態加載兩大類。spa
簡單來講就是隻用JAVA代碼搞定的類型。插件
基於虛擬機的動態加載技術的核心是類加載器ClassLoader,經過它咱們可以加載一些新的類,這種方式也是目前大部分技術文章談到的加載方式。其中,根據ClassLoader使用方式的不一樣,又演變出「熱部署」、「插件化」、「熱修復」等技術。設計
加載外部可執行文件的ClassLoader實例與原APP的ClassLoader實例是互相獨立的(不在同一棵代理樹上),加載進來的新的類與原APP(宿主)裏存在的類互相獨立,根據Java對類的定義,由於這些類的ClassLoader不一樣,因此他們即使包名和類名一致,或者有繼承關係,他們也屬於不懂的類。因此以這種方式加載進來的類與原有的類不能互通,不能污染宿主原有的類,適合用來動態加載一些獨立的業務,好比一些推廣的遊戲,在宿主上提供一個入口,用戶不須要安裝遊戲就能運行。由於這種方式起到不用安裝就能部署遊戲的做用,因此稱爲熱部署。代理
加載外部可執行文件的ClassLoader實例與宿主的ClassLoader實例不是互相獨立的,用宿主的ClassLoader加載過的類就沒法從外部可執行文件中再次加載,它們能夠共用一個公共庫,習慣上把外部可執行文件稱爲插件。插件裏能夠存放公共庫裏一些藉口的實現類,能夠有一些新的Activity或者Service等組件,能夠把一些宿主裏的業務挪到插件中,插件能夠自主升級,不用隨着宿主APP發版。
在使用插件化技術的同時,也可使用插件中的新的類來替換宿主同名的類,這樣就能修復宿主中原有的類存在的BUG。相比插件化,熱修復由於不須要考慮組件和res資源的問題,因此相對簡單得許多,要保證插件種新的類的加載要在加載宿主中原有類的以前。
相信你們都知道打包DEX時65536方法數超標問題,也就是一個DEX只能有65536個方法,所以有了multi-dex的解決方案,把原本只有一個的DEX,拆分紅複數以上的DEX,運行時挨個加載進來,這其實也算是一種動態加載,只不過實現過程對開發者是透明的。
除此以外,還有另外一種拆分DEX是用於減小冷啓動的時間的。冷啓動是指應用第一次從用戶點擊到完成初始化工做的所有過程。隨着如今APP的體積不斷增加,一些APP的DEX文件十分龐大,APP在啓動的時候,單單加載全部的DEX文件就須要很是多的耗時,因此用戶點擊APP的時候會有一個明顯的卡頓過程。所以有一種拆分DEX的方案是「拆分一個啓動閃屏用的DEX,裏面只存放啓動閃屏界面須要用到的類,所以很是小,其餘類放到其餘DEX裏面」,啓動的時候由於只須要加載閃屏的DEX,因此很是快,APP進入閃屏後,經過異步任務去完成其餘DEX的加載,就能消除卡頓的過程。
第一種拆分DEX是官方支持的,開發者只須要打開multi-dex功能便可;第二種拆分DEX則須要開發者本身設計。
基於ClassLoader的動態加載都有個共同的特色,就是新的類一旦加載進內存了,就沒法再次替換了,因此沒法在運行時候升級功能,須要重啓APP才能生效。
有另外一種動態加載方式是工做在Native層的,相比於ClassLoader,在Native層的動態加載不須要從新啓動APP就能生效,這類的加載有 加載SO庫 和 基於JNI HOOK 的熱修復。
加載SO庫是最多見的Native動態加載,咱們項目常常中使用SO庫,編譯APP的時候,SO並不會參與編譯,會原封不動被拷貝到APK包裏的lib目錄下,安裝APK的時候,系統會掃描lib文件夾下支持當前設備CPU類型(好比arm或x86)的SO庫(APK包會帶有多種CPU類型對應的SO庫,安裝的時候只須要對應類型的)並拷貝到系統安裝目錄,APP在運行時能夠調用 System#loadLibrary
方法動態加載對應的SO庫,此外還能夠調用 System#load
加載指定路徑上的SO庫。
如今的APK裏面每每帶有很是多的SO庫,而APP運行時只須要用到對應CPU類型的SO庫,所以把SO庫從APK包裏剝離出來也是APK瘦身的有效手段。
基於JNI HOOK的熱修復技術的表明框架有阿里巴巴的 AndFix。Android中,修復BUG的方式就是更新類的方法,和ClassLoader經過加載新的類來更換方法的實現的想法同樣,AndFix 也是經過更換方法的作法來實現熱修復,不過作法比較取巧。Android中執行Native方法的時候,會去SO庫中查找對應的C/C++方法,而 AndFix 先把普通Java方法用Native方法代替,再經過更換不一樣SO庫還更換Native方法的實現。