Android 插件化的過去-現在-未來 原 薦

本文原創,轉載請以鏈接形式註明地址:http://kymjs.com/code/2016/05/04/01
第一篇文章,作爲序文,並沒有什麼實質性內容,僅僅是一些八卦和歷史,重效率的朋友可以選擇直接跳過。

##過去

三年前,一款名叫【23code】的應用讓廣大 Android 開發者都"紅了眼",並不是他做的多麼酷炫,論內容,他僅僅是一個自定義UI控件集合應用,真正讓人捉摸不透的是他的實現,他可以直接下載一個自定義控件的demo,並且運行起來,這是我知道的最早的插件化開發的應用。
當時,Github上有一個開源的插件化框架,叫 AndroidDynamicLoader ,他使用一個Activity作爲外殼,動態加載一個未安裝apk中的Fragment,並通過外殼Activity來處理Fragment的全部生命週期,達到動態加載一個Android視圖界面的效果。 儘管在現在看來這種實現複雜而麻煩,但在當時應該算是很先進的動態加載思路了。他應該是最早的開源 Android 插件化框架。
兩年前,在 2014 年 4月,一位中國人開源了一個插件化框架,叫 DL。這個名字是作者自己取的,全名爲:dynamic-load-apk。 其實現原理是創建一個靜態代理 Activity,將動態加載到未安裝的 Activity 中的全部方法(包括生命週期方法)使用靜態代理類調用執行。然而由於是動態加載的類,靜態代理調用後沒有辦法拿到super,只能在編寫插件時使用that來替代super,而這個that對象實際上就是靜態代理類。這應該是最早的國產開源插件化框架了。
同年5月,我在讀了DL的全部源碼後,完成了自己的第一個插件化框架:CJFrameForAndroid,其實就只是在DL的基礎上加入了 Service 的動態加載和Activitylaunchmode 以及插件頁面間的數據傳遞。
同樣是 2014年7月(或者8月),一位名叫 null 的朋友(中國人),寫了一個插件化加載框架,叫android-pluginmgr 利用 java 虛擬機字節碼操作方式,通過動態生成一個插件類的子類,達到插件化的功能。儘管熱編譯(或者叫熱部署)首次創建時效率非常低,但是首次創建後下次加載就能達到比起反射調用快的多的效果,同時可以做到插件代碼不必遵循任何限定。這個新的思路讓我眼前一亮。然而現在,看到他的master分支已經與 lody 一起,改成了Instrumentation加載,而 dev 分支還保留着我的first commit真的很抱歉,當時答應 null 的到現在也沒做到,很遺憾,也感謝你一直保留 dev tree 到現在。
2014年11月,11月份,當時高一剛入學3個月的 lody 也寫了一個插件化框架,叫Direct-Load-apk這個庫已經被刪除了,現在你看到的是一個別人fork的倉庫,原因咱們最後講八卦 ) 這個庫我給他起名 DLA,最初跟 lody 說的時候他還鬧着跟我爭冠名權,明明就是我先說的。DLA使用的應該是當時最先進方案了,以至於第二年的DroidPluginDynamicAPK都採用的是這套方案,只不過實現起來更爲嚴謹。通過找到一切Activity啓動的根源:Instrumentation通過替換這個類,來加載一個僞裝的Activity欺騙系統的校驗,而實際上加載的是未安裝的插件Activity。

##現在

今年似乎並沒有什麼新的插件化項目了,所以就從去年說起了。
15年最早出的是阿里的熱修復技術:AndFix 通過加載器讀取一個dex文件中的類,並找到被註解標記到的要修復的方法,再通過jni在C層替換掉原本出BUG的方法的指針,從而達到熱修復的目的。這套方案作爲熱修復而言並沒有任何問題可言,但是熱修復畢竟是熱修復,不能達到動態添加的目的。
隨後還有QQ空間的熱修復方案:MultiDex的思路,在應用啓動的時候,往ClassloaderPathList裏面插入一個Dex,通過覆蓋掉出BUG的類來做到熱修復。QQ空間只出了理論方案,而這套方案的開源代碼實現,則是由 賈吉鑫 寫了一個 nuwa 託管在了 Github 上。
相關的熱修復項目還有幾個就不一一講解了,咱們繼續看下半年出的幾個插件化項目。

2015年8月,當時還在360手機助手的張勇開源了一個插件化框架,叫:DroidPlugin 跟上面說的DLA一樣,通過修改Instrumentation實現Activity動態加載,通過修改ActivityThread實現Service動態加載。說起來非常容易,但是實際上實現起來應該是困難重重。作者幾乎是完全自己實現了一套Framework層中對Service和Activity加載的方案,替換掉了系統幾乎全部相關的Binder
同年10月,攜程的也開源了其插件化框架:DynamicAPK,內容沒細看,據說最成功的是自己實現了一個aapt,替換掉SDK的aapt後可以做到對插件資源重排,達到資源通用。
2016年初開源的一個項目:Small,不光有Android的插件化功能,同時作者還提供了IOS的實現代碼。這個項目融合了熱修復的類替換思路和插件化的資源加載,是一個非常好的思路。項目的 java 代碼本身並沒有什麼特殊的地方,跟上面講的差不多,主要內容是在 groovy 腳本里面,通過腳本修改了編譯後生成的插件資源id。還沒看完,不敢做評價。

##未來

說到未來,也不得不提去年出來的ReactNative,儘管我一直說他不可能會成爲最終方案,但移動應用web化一定是一個必然的趨勢,就好像曾經的桌面應用由C/S到B/S的轉變。而怎麼web化纔是關鍵之處。
馮老師之前說過,他走的時候已經開始有團隊着手研究基於頁面級別的動態加載了。什麼是基於頁面級別,想想今天的瀏覽器,只有在你真正想要瀏覽那個頁面時,纔去加載那個頁面的內容。移動應用中的2/8定律,80%的用戶訪問20%的頁面,那麼剩下80%的頁面是沒必要用戶去下載的,只有在用到的時候去下載。隨着最近重新撿起被我扔掉兩年的插件化開發知識,也慢慢感觸到這種方案似乎真的是可行的。
再說回RN,呵呵噠,一個HelloWorld項目就是8M+,這什麼概念?一個so文件6M什麼概念?我敢下斷言,拋開阿里的 WeeX 不提,今年下半年絕對還會出基於RN這種思路的web應用框架,而且只會做的更好。
不過這裏提一個思路,也是最近團隊內部分享的時候想到的,既然RN僅僅是so包很大,他的增量bundle還是很小的,那麼有沒有可能通過插件化的方案,動態加載這些so包,來解決這個問題?雖然馬上就被同事拋來:"那沒網怎麼辦?"這種尷尬的問題。。。

##聊點別的

上文講了一個叫DL的項目,相信如果是瞭解過的人,應該都清楚,作者叫任玉剛,原點心桌面的後來被百度收購後到了百度衛士,很多人叫他主席因爲最初在他QQ羣裏面等級排行最高的稱呼叫主席。任老師寫過一篇博客,叫:《樹立個人品牌:讓名企hr們主動來找你》講的很在理,原文的點擊量已經有15225了。前幾天五一去北京,跟廖祜秋 聊到一件事,說現在的技術社區越來越浮躁了。swiftcon剛剛結束,會上某嘉賓打醬油被各種吐槽,一個技術會議居然找了一些辣妹去跳舞,以及直播寫代碼的美女也做技術分享了。微博上各位大V網紅也都開始建立收費羣,粉絲紅利時代大家都想分到一杯羹。
可是各位想成爲網紅的朋友,有沒有想過在你樹立個人品牌的時候,是否有想過拿什麼來支撐你的品牌,站在風口豬也能飛,可飛遠了以後是沒有風了的,需要靠你自己的翅膀了。
最初在寫 CJFrameForAndroid 的時候,被某個人威逼利誘過,說項目涉及抄襲,要求加上協作者聲明,並在項目主頁加上鍊接,如果這樣做了,可以在他火起來了以後,在博客幫我做宣傳推廣。同樣的DLA爲什麼會刪庫,據我所知也是有些外力摻和,雖然 lody 並沒有跟我說什麼。
再說到前幾個月,有人利用Github的watchlist,擅自將很多GitHub排名較高的人加入了列表中,從那以後,該項目不管做了什麼改動,在列表中的人都會收到一份通知郵件。爲此 JakeWharton 還特意回覆他讓他不要再這麼做了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章