Android 組件化和插件化詳解

1. Android 組件化

    1. 組件化開(kāi)發(fā)可以有效降低代碼模塊的耦合度,使代碼架構(gòu)更加清晰,同時(shí)模塊化的編譯可以有效減少編譯時(shí)間,當(dāng)然總的編譯時(shí)間是不會(huì)減少的畦木,只是App模塊化之后開(kāi)發(fā)某個(gè)模塊時(shí),只需要編譯特定模塊砸泛,可以快速編譯調(diào)試
    1. 將一個(gè)Module拆分成若干個(gè)Module十籍,由主App提供統(tǒng)一的入口,每個(gè)拆分后的Module都依賴共享的Common依賴庫(kù)唇礁,通過(guò)相關(guān)配置勾栗,各個(gè)Module可以獨(dú)立運(yùn)行調(diào)試,也可以供主App依賴使用盏筐。
    1. ARouter 原理

ARouter 核心實(shí)現(xiàn)思路是围俘,我們?cè)诖a里加入的 @Route 注解,會(huì)在編譯時(shí)期通 過(guò) apt生成一些存儲(chǔ) pathactivityClass映射關(guān)系的類(lèi)文件琢融,然后 app進(jìn)程啟動(dòng)的時(shí)候會(huì)拿到這些類(lèi)文件界牡,把保存這些映射關(guān)系的數(shù)據(jù)讀到內(nèi)存里(保存在 map 里),然后在進(jìn)行路由跳轉(zhuǎn)的時(shí)候漾抬,通過(guò) build() 方法傳入要到達(dá)頁(yè)面的路由 地址欢揖,ARouter會(huì)通過(guò)它自己存儲(chǔ)的路由表找到路由地址對(duì)應(yīng)的 Activity.class(activity.class = map.get(path)),然后 new Intent()奋蔚,當(dāng)調(diào)用 ARouterwithString()方法它的內(nèi)部會(huì)調(diào)用 intent.putExtra(String name, String value), 調(diào)用 navigation()方法烈钞,它的內(nèi)部會(huì)調(diào)用startActivity(intent)進(jìn)行跳轉(zhuǎn)泊碑,這樣便可 以實(shí)現(xiàn)兩個(gè)相互沒(méi)有依賴的 module順利的啟動(dòng)對(duì)方的 Activity.

3.1 ARouter的原理就是所有的moudle都引用ARouter,然后再moudle中去生成一個(gè)映射表毯欣,然后再把這個(gè)映射表傳到ARouter
3.2 映射表生成 , 我們一般配置ARouter會(huì)這樣寫(xiě)

@Route(path = xxx/xxx)
public class xxx{
    ......
  }

3.3 發(fā)起跳轉(zhuǎn)

ARouter.getInstance().build("/user/UserMainActivity").navigation()

ARouter的代碼要簡(jiǎn)潔很多馒过,完全不需要手動(dòng)注冊(cè)路由就可完成跳轉(zhuǎn),它是怎么做到的呢酗钞?
3.4 很神奇腹忽!與前篇我們實(shí)現(xiàn)的路由相比,ARouter的代碼要簡(jiǎn)潔很多砚作,完全不需要手動(dòng)注冊(cè)路由就可完成跳轉(zhuǎn)窘奏,它是怎么做到的呢?
通過(guò)跟進(jìn)navigation()函數(shù)調(diào)用過(guò)程葫录,我們把目光聚焦到兩個(gè)容器中:

  // ARouter源碼
class Warehouse {
    // Cache route and metas
    //用于存儲(chǔ)所有的路由組
    static Map<String, Class<? extends IRouteGroup>> groupsIndex = new HashMap<>();
    //用于存儲(chǔ)已注冊(cè)的所有路由
    static Map<String, RouteMeta> routes = new HashMap<>();  
  
    ...
}

public interface IRouteGroup {
    /**
     * Fill the atlas with routes in group.
     * atlas用于存儲(chǔ)當(dāng)前組里的所有路由着裹,實(shí)際傳入的就是Warehouse.routes
     */
    void loadInto(Map<String, RouteMeta> atlas);
}
 // 路由包裝類(lèi),路由目標(biāo)的Class對(duì)象就存儲(chǔ)在這里面
public class RouteMeta {
    private RouteType type;         // Type of route
    private Element rawType;        // Raw type of route
    private Class<?> destination;   // Destination
    private String path;            // Path of route
    private String group;           // Group of route
    private int priority = -1;      // The smaller the number, the higher the priority
    private int extra;              // Extra data
    private Map<String, Integer> paramsType;  // Param type
    private String name;
    
    ...
}
  • ARouter對(duì)路由提出了分組概念米同,上面 UserMainActivity就屬于user組下骇扇,當(dāng)路由path存在2級(jí)及以上時(shí)摔竿,group字段也可以省略,ARouter默認(rèn)會(huì)使用第一個(gè)反斜杠后面的path作為組名
// group可省略不寫(xiě)
@Route(path = "/user/UserMainActivity")
class UserMainActivity : AppCompatActivity() {
      ...
}
  • 一般情況下少孝,我們會(huì)將同一模塊的路由劃分在同一個(gè)組下继低,例如App模塊下的所有路由都在“app”這個(gè)分組下 , user模塊的路由都在“user”分組下;當(dāng)然稍走,同一模塊擁有多個(gè)分組也是完全可行的袁翁,只要保證與其它模塊中的路由分組不重名即可

分析這兩個(gè)容器的作用,大致如下:
1钱磅、當(dāng)傳入path進(jìn)行跳轉(zhuǎn)時(shí)梦裂,優(yōu)先從Warehouse.routes中直接獲取路由對(duì)象;
2盖淡、路由對(duì)象不存在年柠,就需要通過(guò)Warehouse.groupsIndex路由組來(lái)完成注冊(cè)功能
3、注冊(cè)成功后褪迟,當(dāng)前path所在組的所有路由都將存儲(chǔ)到Warehouse.routes中冗恨;
4、回到第1步味赃,獲取路由對(duì)象掀抹;
5、讀取路由對(duì)象信息心俗;
6傲武、完成跳轉(zhuǎn)

2. Android 插件化

    1. 隨著apk越來(lái)越大,各種業(yè)務(wù)邏輯越來(lái)越繁雜城榛,會(huì)達(dá)到apk開(kāi)發(fā)的一個(gè)瓶頸揪利;從業(yè)務(wù)上說(shuō),業(yè)務(wù)的繁雜會(huì)導(dǎo)致代碼急劇的膨脹狠持,當(dāng)代碼中的方法數(shù)超過(guò)65535時(shí)疟位,就無(wú)法再容納創(chuàng)建新的方法。插件化時(shí)將 apk 分為宿主和插件部分喘垂,插件在需要的時(shí)候才加載進(jìn)來(lái).
    1. 插件化的優(yōu)點(diǎn)
  • 宿主和插件分開(kāi)編譯
  • 并發(fā)開(kāi)發(fā)甜刻,宿主和插件都是apk,開(kāi)發(fā)是互不影響的正勒,只需要宿主給插件一個(gè)上下文
  • 動(dòng)態(tài)更新插件得院,不需要安裝,下載之后就可以直接打開(kāi)
  • 按需下載模塊
  • 可以解決方法數(shù)或變量數(shù)爆棚問(wèn)題
    1. Android中的ClassLoader
      在Android系統(tǒng)中ClassLoader是用來(lái)加載dex文件的昭齐,有包含 dex 的 apk 文件以及 jar 文件尿招,dex 文件是一種對(duì)class文件優(yōu)化的產(chǎn)物,在Android中應(yīng)用打包時(shí)會(huì)把所有class文件進(jìn)行合并、優(yōu)化(把不同的class文件重復(fù)的東西只保留一份)就谜,然后生成一個(gè)最終的class.dex文件
    1. PathClassLoader用來(lái)加載系統(tǒng)類(lèi)和應(yīng)用程序類(lèi)怪蔑,可以加載已經(jīng)安裝的 apk目錄下的 dex文件
public class PathClassLoader extends BaseDexClassLoader {
    public PathClassLoader(String dexPath, ClassLoader parent) {
        super(dexPath, null, null, parent);
    }

    public PathClassLoader(String dexPath, String libraryPath,
            ClassLoader parent) {
        super(dexPath, null, libraryPath, parent);
    }
}
    1. DexClassLoader用來(lái)加載 dex文件,可以從存儲(chǔ)空間加載 dex文件丧荐。
public class DexClassLoader extends BaseDexClassLoader {
    public DexClassLoader(String dexPath, String optimizedDirectory,
            String libraryPath, ClassLoader parent) {
        super(dexPath, new File(optimizedDirectory), libraryPath, parent);
    }
}

插件化中一般使用的是 DexClassLoader

3. 組件化和插件化的區(qū)別 ?

  1. 組件化 : 是將一個(gè)App分成多個(gè)模塊缆瓣,每個(gè)模塊都是一個(gè)組件(module),開(kāi)發(fā)過(guò)程中可以讓這些組件相互依賴或獨(dú)立編譯虹统、調(diào)試部分組件弓坞,但是這些組件最終會(huì)合并成一個(gè)完整的Apk去發(fā)布到應(yīng)用市場(chǎng)。
  2. 插件化 : 是將整個(gè)App拆分成很多模塊车荔,每個(gè)模塊都是一個(gè)Apk(組件化的每個(gè)模塊是一個(gè)lib)渡冻,最終打包的時(shí)候?qū)⑺拗鰽pk和插件Apk分開(kāi)打包,只需發(fā)布宿主Apk到應(yīng)用市場(chǎng)忧便,插件Apk通過(guò)動(dòng)態(tài)按需下發(fā)到宿主Apk
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末族吻,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子珠增,更是在濱河造成了極大的恐慌超歌,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蒂教,死亡現(xiàn)場(chǎng)離奇詭異巍举,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)凝垛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)懊悯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人梦皮,你說(shuō)我怎么就攤上這事定枷。” “怎么了届氢?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)覆旭。 經(jīng)常有香客問(wèn)我退子,道長(zhǎng),這世上最難降的妖魔是什么型将? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任寂祥,我火速辦了婚禮,結(jié)果婚禮上七兜,老公的妹妹穿的比我還像新娘丸凭。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布惜犀。 她就那樣靜靜地躺著铛碑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪虽界。 梳的紋絲不亂的頭發(fā)上汽烦,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音莉御,去河邊找鬼撇吞。 笑死,一個(gè)胖子當(dāng)著我的面吹牛礁叔,可吹牛的內(nèi)容都是我干的牍颈。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼琅关,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼煮岁!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起死姚,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤人乓,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后都毒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體色罚,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年账劲,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了戳护。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡瀑焦,死狀恐怖腌且,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情榛瓮,我是刑警寧澤铺董,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站禀晓,受9級(jí)特大地震影響精续,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜粹懒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一重付、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧凫乖,春花似錦确垫、人聲如沸弓颈。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)翔冀。三九已至,卻和暖如春爬迟,著一層夾襖步出監(jiān)牢的瞬間橘蜜,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工付呕, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留计福,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓徽职,卻偏偏與公主長(zhǎng)得像象颖,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子姆钉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容