一、問題提出
一般的,一個Android應用在開發到了一定階段以后,功能模塊將會越來越多,APK安裝包也越來越大,用戶在使用過程中也沒有辦法選擇性的加載自己需要的功能模塊。此時可能就需要考慮如何分拆整個應用了。
當前問題:
1.代碼越來越龐大,很難維護
2.需求越來越多,某一模塊的小改動都要重新發布版本,發布時間越來越不可控。
3.項目中某一段代碼牽涉模塊越來越多,應對bug反應越來越慢。
潛在問題:
早期的Dalvik VM內部使用short類型變量來標識方法的id,dex限制了程序的最大方法數是
65535,如果超過最大限制,無法編譯,(此外補充一點,之前做Framework開發時候,曾遇到多方法數量超過65535編譯不通過,修改makefile,從外部(一般是源碼目錄下Vender/xx/xx/xx...)加載類既可以解決)。
二、解決方案提出
1.用Html5代替部分邏輯
2.刪除無用代碼,減少方法數
3.插件化,將一個 App 划分為多個插件(Apk 或相關格式)
前兩種方法在某種條件下可以解決問題,但是治標不治本。下面我們重點說一下
Android插件化開發。
三、Android插件化
Android 插件化 —— 指將一個程序划分為不同的部分,比如一般 App 的皮膚樣式就可以看成一個插件
Android 組件化 —— 這個概念實際跟上面相差不那么明顯,組件和插件較大的區別就是:組件是指通用及復用性較高的構件,比如圖片緩存就可以看成一個組件被多個 App 共用
Android 動態加載 —— 這個實際是更高層次的概念,也有叫法是熱加載或 Android 動態部署,指容器(App)在運⾏狀態下動態加載某個模塊,從而新增功能或改變某⼀部分行為
Android 組件化 —— 這個概念實際跟上面相差不那么明顯,組件和插件較大的區別就是:組件是指通用及復用性較高的構件,比如圖片緩存就可以看成一個組件被多個 App 共用
Android 動態加載 —— 這個實際是更高層次的概念,也有叫法是熱加載或 Android 動態部署,指容器(App)在運⾏狀態下動態加載某個模塊,從而新增功能或改變某⼀部分行為
在java開發中隨處可見使用jar包的插件機制進行開發,但在android中,目前較成熟的插件機制基本沒有,看到的帖子中提到了重寫dexclassloader可以完美的解決插件問題,但都只簡要描述了原理,沒有源碼或關鍵代碼,下面對網絡中的思路進行總結.
目前插件包有兩種格式:一種是apk,一種是dex包.對插件的接入機制來說也有兩種:一種是需要安裝,一種是不需要安裝.結合插件包的格式來說插件的方式只有三種:1,apk安裝,2,apk不安裝,3,dex包.三種方式其實主要是解決兩個方面的問題:1,加載插件中的類,2,加載插件中的資源.第一個加載類的問題,這三個方式都可以很好的解決.但目前三種方式都沒有很完美的解決第2個問題.
1,apk安裝方式.插件apk安裝后,可以在主程序中通過包名加載到插件的context,有了插件的context就可以解決加載插件資源的問題.但出現的新問題是:如果插件a,b,c間公用一個底層jar包,那么在abc間傳送數據時,需要進行序列化和反序列化,因為a中jar包的data類與b中jar包的data類雖然都是同樣的jar包也是同樣的類,但兩個類在java機制來是由不同的classloader加載的,是不同的類.那么就會出現插件間jar包冗余和數據傳遞的效率不好問題.總之能解決問題.
2,apk不安裝,這個是不推薦的方式.可以通過dexclassloader加載到插件a中的類,但插件沒有安裝就無法獲得插件apk的context,也就無法加載到資源,網絡上有牛人通過將主程序的context替換關鍵的對象(如classloader,assertmanager等),偽造成插件的context,然后通過偽context也可以獲得插件資源.目前個人驗證的問題為:獲取到的layout資源中的textview顯示文本有問題,無法顯示在layout設定的文本.同時個人猜測這種hack的方式或許有其它的未知的問題,但不排除高手已經解決了這個問題.
3,dex包,這個基本是java開發中jar包的方式.同樣通過dexclassloader加載到插件中的類,但依舊沒有context,也無法加載到資源.要使用布局,只能在插件中使用java代碼來寫布局.這種方式最簡單(1,類似jar包的方式,也可以隨意導出單個類的jar包然后轉化為dex包,不存在打包成apk需要完整的工程和依賴關系的要求.2,底層的公用jar包所有插件可以公共一個,傳遞數據不用反復的序列化和反序列化.),也是最復雜的(布局文件全部代碼寫,難調試,難維護).
四、優缺點
插件式開發通俗的講就是把一個很大的app分成n多個比較小的app,其中有一個app是主app。基本上可以理解為讓一個apk不安裝也可以被運行。只不過這個運行是有很多限制的運行,所以才叫插件否則就叫病毒了。其實在目前淘寶、百度、騰訊、等都有成熟的動態加載框架,包括apkplug,但是它們都是不開源的。
優點:
1.模塊解耦
2.解除單個dex函數不能超過
65535的限制
3.動態升級
4.高效開發(編譯速度更快)
基於插件的開發列舉兩個比較突出的優點:
1、應用程序非常容易擴展,比如一個新的領域要加到舊的應用程序中,只需把這個新的領域做為一個插件,只開發這個小的app就可以了,舊的應用程序可能會原分不動,就連編譯打包都不需要。
2、下載更新特別省流量,假如一個應用程序有10M把它分成兩個的話可能每次更新只需要花費5M或者更少的流量就可以更新完。
追求完美本來就是一種性格缺陷,說在做軟件方面沒有近乎完美。基於插件開發當然不是插件越多越好能掌控好內聚和耦合度就更好了。插件增加了主應用程序中的邏輯難度。有優點的東西也是有缺點的這是必然。
缺點:
1.增加了主應用程序的邏輯難度
2.技術有難度,目前一些成熟的框架都是閉源的
參考資料:
1.android插件化及動態部署 - ATLAS--伯奎(阿里無線事業部無線技術專家)
2.怎么將 Android 程序做成插件化的形式?--知乎
3.Android 插件化 動態升級
4.apkplug框架
5.Android插件化開發,初入殿堂
6.Android 插件框架 AtlasForAndroid(阿里使用框架)
Simple Project