最近在了解公司的項目,第一次接觸Android插件化,了解其重要性,於是就開始了插件化的學習。本篇文章把插件化入門過程中的一些技術點整理下來,方便一些初入門的同學一起學習。
所謂插件化,就是讓我們的應用不必再像原來一樣把所有的內容都放在一個apk中,可以把一些功能和邏輯單獨抽出來放在插件apk中,然後主apk做到[按需調用],這樣的好處是一來可以減少主apk的體積,讓應用更輕便,二來可以做到熱插拔,更加動態化。
類的載入可以使用Java的ClassLoader機制,但是對於Android來說,並不是說類載入進來就可以用了,很多組件都是有「生命」的;因此對於這些有血有肉的類,必須給它們注入活力,也就是所謂的組件生命周期管理;
資源載入方案大家使用的原理都差不多,都是用AssetManager的隱藏方法addAssetPath。
要想實現載入外部dex文件(即插件)來實現熱部署,那麼必然要把其中的class文件載入到內存中。
其中涉及到兩種ClassLoader:DexClassLoader和PathClassLoader。而DexClassLoader可以載入外部的jar,dex等文件,正是我們需要的。
關於ClassLoader詳解,見ClassLoader完全解析。
因為插件apk與宿主apk不在一個apk內,那麼一些類的訪問必然要通過反射進行獲取。所以了解反射對插件化的學習是必須的。
關於Java反射,見Java反射詳解。
res里的每一個資源都會在R.java里生成一個對應的Integer類型的id,APP啟動時會先把R.java註冊到當前的上下文環境,我們在代碼里以R文件的方式使用資源時正是通過使用這些id訪問res資源,然而插件的R.java並沒有註冊到當前的上下文環境,所以插件的res資源也就無法通過id使用了。
查看源碼,通過「addAssetPath」方法重新生成一個新的Resource對象來保存插件中的資源,避免衝突。
關於插件資源訪問,見使用插件中的R資源。
插件化實現的過程主要靠欺上瞞下,坑蒙拐騙來實現。想想雖然載入進來了Activity等組件,但也僅僅是最為一個對象而存在,並沒有在AndroidManifest中註冊,沒有生命周期的回調,並不能實現我們想要的效果。因此無論是dynamic_load_apk通過代理activity來操控插件activity的方式,還是DroidPlugin通過hook activity啟動過程來啟動插件activity的方式,都是對代理模式的應用。
關於代理模式,見靜態代理與動態代理。
至此,通過ClassLoader載入,然後通過代理模式讓Activity等組件具有生命周期實現真正的功能,並且解決了資源訪問問題。可能插件化已經可以簡單的實現一些初步的功能,然而插件化絕不止於此。更多的內容仍需要進一步探索,不過以上知識是基礎中的基礎,必備之必備。
介紹一下其中比較重要的兩個,實現思想不同,也是入門插件化可以學習的兩個。
Dynamic-Load-Apk簡稱DL,這個開源框架作者是任玉剛,他的實現方式是,在宿主中埋一個代理Activity,更改ClassLoader後找到載入插件中的Activity,使用宿主中的Activity作為代理,回調給插件中Activity所以對應的生命周期。這個思路與AndroidDynamicLoader有點像,都是做一個代理,只不過Dynamic-load-apk載入的插件中的Activity。
DroidPlugin是張勇實現的一套插件化方案,它的原理是Hook客戶端一側的系統Api。
既然著重介紹了兩個項目,必然要學起來,怎麼學習呢?
好在已經有前人把自己的學習經驗分享出來,那麼我們只需要結合源碼進行學習即可。
Android插件化學習之路(一)之動態載入綜述
Android插件化學習之路(二)之ClassLoader完全解析
Hook機制之動態代理
Activity生命周期管理
以上內容僅是Android插件化的入門知識,目前認知尚淺。
插件化、熱更新等技術在2016開始迅速發展,這即是業務發展的需求,也是我們需要緊跟前沿學習的技術。
沒錯,年初我花了一個多月的時間整理出來的學習資料,希望能幫助那些想進階提升Android開發,卻又不知道怎麼進階學習的朋友。【包括高級UI、性能優化、架構師課程、NDK、Kotlin、混合式開發(ReactNative+Weex)、Flutter等架構技術資料】,希望能幫助到您面試前的複習且找到一個好的工作,也節省大家在網上搜索資料的時間來學習。
推薦閱讀: