轉(zhuǎn)載自http://www.chopiter.com/android_plugin/
本文旨在梳理Android插件化的歷史及對(duì)比各家技術(shù)能解決的問(wèn)題,對(duì)比出優(yōu)缺點(diǎn)。既是Android插件化的總結(jié),又可以當(dāng)做插件化入門(mén)的引導(dǎo)。本文不對(duì)技術(shù)細(xì)節(jié)過(guò)多探討,細(xì)節(jié)方面會(huì)有相應(yīng)的參考鏈接。
一、歷史
插件化的歷史已經(jīng)有很長(zhǎng)一段時(shí)間了,各種大大們也介紹過(guò)插件化相關(guān)的歷史,比如:
包建強(qiáng)的:Android插件化:從入門(mén)到放棄
T大:Android 插件化 動(dòng)態(tài)升級(jí)
張濤:Android 插件化的 過(guò)去 現(xiàn)在 未來(lái)
按照時(shí)間維度來(lái)看,整理成以下表格:

AndroidDynamicLoader
AndroidDynamicLoader的作者是大眾點(diǎn)評(píng)的屠毅敏,應(yīng)該是最早的動(dòng)態(tài)加載實(shí)現(xiàn)方案了。作者在介紹這個(gè)框架時(shí)形容宿主App就好像瀏覽器,但它加載的并不是網(wǎng)頁(yè),而是運(yùn)行在Android系統(tǒng)上的插件。這個(gè)方案主要是在插件中使用Fragment,在宿主中使用Activity去動(dòng)態(tài)加載插件中的Fragment。
github鏈接:https://github.com/mmin18/AndroidDynamicLoader
23Code
23Code并不是一個(gè)開(kāi)源的項(xiàng)目,它是一個(gè)完整的apk。在應(yīng)用市場(chǎng)可以下載得到,它內(nèi)部展示了一些有趣的動(dòng)效,通過(guò)下載的方式,可以直接運(yùn)行起來(lái),這就是插件化的真實(shí)案例。
Altas
altas是阿里的伯奎分享出來(lái)的一個(gè)插件化的方案。
分享視頻鏈接:http://v.youku.com/v_show/id_XNTMzMjYzMzM2.html
對(duì)應(yīng)的PPT:http://club.alibabatech.org/resource_detail.htm?topicId=84
這里的分享主要是將一些思路,業(yè)務(wù)方面的場(chǎng)景,解決的問(wèn)題。后來(lái)github上有了對(duì)應(yīng)的開(kāi)源項(xiàng)目叫OpenAltas,后改名ACDD。
ACDD的鏈接:https://github.com/bunnyblue/ACDD
官方對(duì)這個(gè)庫(kù)的說(shuō)明是非代理Android動(dòng)態(tài)熱部署框架,而且在視頻介紹中,伯奎也講到,這個(gè)方案,就是把宿主當(dāng)做一個(gè)容器,動(dòng)態(tài)加載對(duì)應(yīng)的插件。視頻中也有講到,要做到讓插件無(wú)感知地運(yùn)行在這個(gè)容器中,需要hook很多系統(tǒng)層面的東西,比如:ActivityThread,LoadedApk,ContextImpl,PackageParser,ActivityManagerNative等,即當(dāng)插件需要系統(tǒng)的服務(wù)來(lái)提供對(duì)應(yīng)功能的時(shí)候,將這個(gè)行為攔截掉,宿主就可以在插件和Android系統(tǒng)中間做些手腳了。在當(dāng)時(shí),Altas是最為先進(jìn)插件化技術(shù)了。為淘寶客戶(hù)端提供了很多加載其他業(yè)務(wù)插件的能力。
Dynamic-load-apk
Dynamic-Load-Apk簡(jiǎn)稱(chēng)DL,這個(gè)開(kāi)源框架作者是任玉剛,他的實(shí)現(xiàn)方式是,在宿主中埋一個(gè)代理Activity,更改ClassLoader后找到加載插件中的Activity,使用宿主中的Activity作為代理,回調(diào)給插件中Activity所以對(duì)應(yīng)的生命周期。這個(gè)思路與AndroidDynamicLoader有點(diǎn)像,都是做一個(gè)代理,只不過(guò)Dynamic-load-apk加載的插件中的Activity。
項(xiàng)目地址:https://github.com/singwhatiwanna/dynamic-load-apk
項(xiàng)目說(shuō)明:http://blog.csdn.net/singwhatiwanna/article/details/40283117
DroidPlugin
DroidPlugin是張勇實(shí)現(xiàn)的一套插件化方案,它的原理也是Hook客戶(hù)端一側(cè)的系統(tǒng)Api,可能與Altas所Hook的點(diǎn)不同,細(xì)想應(yīng)該是基本相同的。
項(xiàng)目地址:https://github.com/DroidPluginTeam/DroidPlugin
項(xiàng)目中DOC文件夾有很多關(guān)于項(xiàng)目的講解說(shuō)明。
張勇本人對(duì)DroidPlugin的講解:http://www.infoq.com/cn/presentations/the-realization-principle-and-application-of-droidplugin?utm_campaign=rightbar_v2&utm_source=infoq&utm_medium=presentations_link&utm_content=link_text
維術(shù)對(duì)這個(gè)框架的講解:http://weishu.me/2016/01/28/understand-plugin-framework-overview/
維術(shù)的這幾篇blog很詳細(xì)滴講解了DroidPlugin是如何實(shí)現(xiàn)四大組件的插件化的,還有幾篇有規(guī)劃但是沒(méi)有寫(xiě)的方面,希望后面能補(bǔ)全。
VirtualApp
VirtualApp作者是高中生羅迪,據(jù)說(shuō)這個(gè)Android大牛初三的時(shí)候就開(kāi)始研究雙開(kāi)、插件化的技術(shù),相當(dāng)了不起。項(xiàng)目的思路與DroidPlugin相似,不過(guò)他沒(méi)有提供Service的代理,而是使用ContentProvider來(lái)代替Service在宿主中作為真正的運(yùn)行體。
項(xiàng)目地址:https://github.com/asLody/VirtualApp
DynamicAPK
DynamicAPK是攜程推出的動(dòng)態(tài)加載方案
項(xiàng)目說(shuō)明:http://www.infoq.com/cn/articles/ctrip-android-dynamic-loading
項(xiàng)目地址:https://github.com/CtripMobile/DynamicAPK
與ACDD一樣修改了aapt,使得插件與宿主的資源不會(huì)出現(xiàn)相同id的問(wèn)題。
熱修復(fù)
插件化技術(shù)的演進(jìn),帶來(lái)了相關(guān)的熱修復(fù)技術(shù)。有代表的熱修復(fù)技術(shù)有:
- QQ空間的超級(jí)補(bǔ)丁技術(shù)
- 微信Tinker
- 阿里的AndFix
QQ空間和微信的Tinker的細(xì)想很相近,都是在查找類(lèi)的之前,將插件的dex插入原有dex之前,使得能夠加載的是最新插入進(jìn)來(lái)的dex中的class。從而達(dá)到修復(fù)原有類(lèi)的問(wèn)題的目的。它們并沒(méi)有在Github上開(kāi)源,賈吉鑫根據(jù)這個(gè)思路做出了Nuwa開(kāi)源道github上,之后又有很多類(lèi)似的開(kāi)源項(xiàng)目。阿里的AndFix與這種思路不同,它采用的是方法替換的思路,在native層,把這個(gè)方法實(shí)現(xiàn)體的指針替換為修復(fù)后的方法。
這兩種方案其實(shí)都有很多弊端,QQ空間的類(lèi)替換方法,不能即時(shí)生效,patch如果修復(fù)的地方比較多,會(huì)影響啟動(dòng)時(shí)間。而AndFix,則只支持方法層面的替換,不能使用未import過(guò)的類(lèi),不能替換整個(gè)類(lèi)文件。
美團(tuán)有一種叫做Robust的熱修復(fù)方案
鏈接:http://tech.meituan.com/android_robust.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io
它應(yīng)該是性能與修復(fù)場(chǎng)景最好的一種了。它的思想與InstantRun一樣,在編譯時(shí)動(dòng)態(tài)地為每個(gè)類(lèi)中的每個(gè)方法插樁,每個(gè)方法判斷是否有插件被加載,有的話(huà)直接執(zhí)行插件中的方法。