激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Android - Android模塊化架構(gòu)下,子模塊自加載方案!

Android模塊化架構(gòu)下,子模塊自加載方案!

2021-12-14 22:14掘金少冰半糖檸檬茶 Android

背景在 Android 模塊化架構(gòu)中后,子Module 間相互解耦,作為獨(dú)立的模塊運(yùn)行。如果 子Module 也需要進(jìn)初始化的操作,那么該如何做呢?可能你會(huì)說(shuō),直接在 殼App Application的onCreate函數(shù)進(jìn)行初始化就可以了。

背景在 Android 模塊化架構(gòu)中后,子Module 間相互解耦,作為獨(dú)立的模塊運(yùn)行。如果 子Module 也需要進(jìn)初始化的操作,那么該如何做呢?可能你會(huì)說(shuō),直接在 殼App Application的onCreate函數(shù)進(jìn)行初始化就可以了,但這樣會(huì)帶來(lái)一些新的問(wèn)題:

  • 我們并不需要 殼App 去關(guān)注模塊內(nèi)部的業(yè)務(wù),所以每個(gè)模塊的初始化應(yīng)該由自身管理;
  • 并不是所有子模塊的初始化,都需要在 Application onCreate() 時(shí)去進(jìn)行加載,這樣會(huì)極大影響應(yīng)用的啟動(dòng)速度。所以每個(gè)模塊的初始化應(yīng)該按需加載;

Android模塊化架構(gòu)下,子模塊自加載方案!

常見(jiàn)方案及優(yōu)缺點(diǎn)

1、ContentProvider

實(shí)現(xiàn)原理:每個(gè) 子Module 內(nèi)部自定義 ContentProvider ,在應(yīng)用 Application 的 onCreate 函數(shù)執(zhí)行前,系統(tǒng)就會(huì)自動(dòng)的順序調(diào)用 子Module 的 ContentProvider 的 onCreate 函數(shù),也就實(shí)現(xiàn)了 子Module 的自加載功能。例如 WorkManager 也是根據(jù)這個(gè)原理,其內(nèi)部聲明了 ContentProvider 來(lái)實(shí)現(xiàn)這種自加載方案。

Android模塊化架構(gòu)下,子模塊自加載方案!

優(yōu)點(diǎn):

  • 模塊間充分解耦,代碼邊界獨(dú)立

弊端:

  • ContentProvider 的啟動(dòng)是有性能損耗的,在子模塊較多(業(yè)務(wù)邏輯較多的 App,可能會(huì)有幾十個(gè) 子Module )的情況下,有一定的性能損耗;
  • 需要繼承 ContentProvider 類(lèi)并在 AndroidManifes 中聲明,代碼不夠簡(jiǎn)潔和優(yōu)雅;
  • 無(wú)法控制初始化的時(shí)機(jī),在應(yīng)用啟動(dòng)時(shí)就會(huì)初始化所有的子模塊,而初始化本身可能就是一件比較重的業(yè)務(wù)邏輯;

2、ARouter

實(shí)現(xiàn)原理:通過(guò)路由的方式,實(shí)現(xiàn)子Module的初始化。

Android模塊化架構(gòu)下,子模塊自加載方案!

定義通用IPreloadProvider接口

  1. interface IPreloadProvider: IProvider {
  2. fun preload()
  3. }

在主module中進(jìn)行初始化調(diào)用

  1. fun ARouter.preload(context: Context, path: String) {
  2. val preloadProvider = this.build(path).navigation(context.applicationContext) as IPreloadProvider
  3. preloadProvider.preload()
  4. }

優(yōu)點(diǎn):

  • 在多數(shù)場(chǎng)景下,我們都會(huì)使用 ARouter 來(lái)進(jìn)行模塊化設(shè)計(jì),而ARouter天然支持這種路由調(diào)用的方法,簡(jiǎn)單好用;
  • 代碼邊界獨(dú)立,殼App 與 子Modoule 間不需要代碼上的直接依賴(lài);

弊端:

  • 殼App需要關(guān)心 子Module 的業(yè)務(wù),設(shè)計(jì)上有一定的耦合;
  • 初始化的代碼塊容易膨脹,且各個(gè) 子Module 的初始化代碼均在一起,后續(xù)難以閱讀和維護(hù);

3、App Startup

Android模塊化架構(gòu)下,子模塊自加載方案!

優(yōu)點(diǎn):

  • App Startup 是 為了解決因 App 啟動(dòng)時(shí)運(yùn)行多個(gè) ContentProvider 會(huì)增加 App 的啟動(dòng)時(shí)間的問(wèn)題,使用了一個(gè) InitializationProvider 管理多個(gè)依賴(lài)項(xiàng),消除了每個(gè)庫(kù)單獨(dú)使用 ContentProvider 成本,減少初始化時(shí)間;
  • App Startup 可以自動(dòng)初始化 AndroidManifest.xml 文件中 InitializationProvider 下面的 聲明要初始化的模塊,并允許自定義模塊初始化順序;
  • App Startup 提供了一種延遲初始化模塊的方法,減少 App 初始化時(shí)間;

弊端:

  • 使用時(shí)需要修改 AndroidManifest 文件,使用不夠簡(jiǎn)潔;
  • 子Module 功能比較獨(dú)立,且很多情況不需要即時(shí)加載(不需要在應(yīng)用啟動(dòng)就進(jìn)行初始化的動(dòng)作),如果使用延遲加載的話,又需要使用代碼主動(dòng)執(zhí)行初始化操作,那么勢(shì)就必存在對(duì)應(yīng)的引用。而我們的 子Module 依賴(lài)其實(shí)是建議使用 runtimeonly ,減少代碼上的直接依賴(lài);
  • 無(wú)法解決需要時(shí)加載這種需求;
  • 加載時(shí)序是在 Application onCreate 之前,依賴(lài)的通用庫(kù)此時(shí)可能并未被加載成功;

4、方案總結(jié)

所以,我們需要一個(gè)模塊自加載方案,能夠解決上面的問(wèn)題,且能滿(mǎn)足各種場(chǎng)景的需求:

  • 代碼簡(jiǎn)潔,使用方便,邏輯清晰;
  • 子Module 的預(yù)加載或者預(yù)啟動(dòng),由 子Module 自身來(lái)管理,避免與其他模塊的邏輯耦合;
  • 加載時(shí)機(jī)可以控制,能做到即時(shí)加載或者懶加載,避免產(chǎn)生性能損耗;
  • 不產(chǎn)生額外的性能損耗(可接受范圍內(nèi));

模塊化自加載方案(ALoader)

方案: 每個(gè) 子Module 都有自己的 ModuleApplication(虛擬Applicaiton),并定義啟動(dòng)模式,在應(yīng)用 Application 啟動(dòng)時(shí),會(huì)根據(jù)每個(gè) ModuleApplication 的啟動(dòng)模式來(lái)?yè)駲C(jī)調(diào)用其 onCreate() 函數(shù),達(dá)到模塊自加載的目的。

使用非常方便,僅需要在每個(gè) 子Module 內(nèi)創(chuàng)建 ModuleApplicaiton 類(lèi),繼承自IModuleApplication,使用注解:ModuleApplication 定義 initMode 即可。

  1. @ModuleApplication(initMode = InitMode.MAIN)
  2. class LoginModuleApplication : IModuleApplication() {
  3.  
  4. override fun onCreate(context: Context) {
  5. Log.v("ALoader", "Login Module onCreate")
  6. }
  7. }

InitMode:

HUNGRY:餓漢式加載

主要用于加載時(shí)機(jī)較為嚴(yán)格的場(chǎng)景,即應(yīng)用啟動(dòng)后,需要立刻加載該 子Module 的相關(guān)配置。

IDLE:空閑時(shí)加載

主要用于加載時(shí)機(jī)不那么嚴(yán)格的場(chǎng)景。即應(yīng)用啟動(dòng)后,使用 idleHandler 進(jìn)行初始化,達(dá)到空閑時(shí)加載的目的。

LAZY:懶漢式加載

主要用于按需加載的場(chǎng)景。即應(yīng)用啟動(dòng)后,不進(jìn)行該 子Module 的初始化操作,待該 子Module 的 Activity 、 Service 或者相關(guān)邏輯執(zhí)行時(shí),才進(jìn)行 該子Module 的初始化工作,保證功能的正常運(yùn)行。

自加載方案設(shè)計(jì)思路

借鑒了ARouter的實(shí)現(xiàn)原理,模塊自加載方案的核心思想是:通過(guò)Apt技術(shù),生成 InitMode(初始化時(shí)機(jī)) 和 被注解(@ModuleApplication)的組件類(lèi) 的映射關(guān)系的類(lèi)(ALoaderCore),利用這個(gè)保存了映射關(guān)系的類(lèi),ALoader根據(jù) InitMode 尋找到目標(biāo)類(lèi),執(zhí)行其onCreate()函數(shù)。該框架的核心是利用 apt 生成的映射關(guān)系。

Android模塊化架構(gòu)下,子模塊自加載方案!

1、如何提高ALoader的初始化速度

利用緩存和 Gradle 插件,來(lái)提升映射類(lèi)的查找速度,實(shí)現(xiàn)高性能的初始化。

Android模塊化架構(gòu)下,子模塊自加載方案!

2、如何實(shí)現(xiàn)ALoader懶加載的效果

對(duì)于 子Module 懶加載的實(shí)現(xiàn),最重要的是如何識(shí)別到該 子Module 開(kāi)始啟動(dòng),并在此之前進(jìn)行初始化的操作。針對(duì)于多數(shù)的業(yè)務(wù)場(chǎng)景來(lái)講,子Module 的啟動(dòng)通常是伴隨著 四大組件(Activity、Service、ContentProvider、BroadcastReceiver)的啟動(dòng),而我們可以通過(guò) Hook 技術(shù)來(lái)實(shí)現(xiàn)對(duì)四大組件啟動(dòng)的感知,通過(guò)包名的匹配來(lái)識(shí)別到是哪個(gè) 子Module 開(kāi)始啟動(dòng)。以 Activity 和 Service 為例:

  1. fun hookActivityThreadHHandler() {
  2. val aClass = Class.forName("android.app.ActivityThread")
  3. val sCurrentActivityThread: Field = aClass.getDeclaredField("sCurrentActivityThread")
  4. sCurrentActivityThread.isAccessible = true
  5. val activityThread = sCurrentActivityThread.get(aClass)
  6.  
  7. val mHField: Field = aClass.getDeclaredField("mH")
  8. mHField.isAccessible = true
  9. val mh = mHField.get(activityThread) as Handler
  10.  
  11. val handlerClass = Class.forName("android.os.Handler")
  12. val mCallbackField = handlerClass.getDeclaredField("mCallback")
  13. mCallbackField.isAccessible = true
  14. mCallbackField.set(mh, ProxyHandlerCallback())
  15. }
  16.  
  17. class ProxyHandlerCallback : Handler.Callback {
  18.  
  19. override fun handleMessage(msg: Message): Boolean {
  20. when (msg.what) {
  21. LAUNCH_ACTIVITY -> {
  22. // TODO:
  23. }
  24. EXECUTE_TRANSACTION -> {
  25. // TODO:
  26. }
  27. CREATE_SERVICE -> {
  28. // TODO:
  29. }
  30. }
  31. return false
  32. }
  33. }

方案不足之處和優(yōu)化點(diǎn)

該方案的最終目的是:通過(guò)最簡(jiǎn)單的方式,實(shí)現(xiàn)模塊的按需自加載方案。

但是依然還有可以?xún)?yōu)化的地方:

  • App Startup 可以自定義模塊初始化順序,在ALoader方案中,是否也需要集成?
  • 通過(guò) Hook 技術(shù)來(lái)判斷子模塊的啟動(dòng),可能存在兼容性問(wèn)題,是否還有更優(yōu)雅的方式?
  • 是否有其他更復(fù)雜的業(yè)務(wù)場(chǎng)景,還沒(méi)考慮到呢?

當(dāng)然,對(duì)于一般的業(yè)務(wù)場(chǎng)景,ALoader的實(shí)現(xiàn)已經(jīng)足夠滿(mǎn)足需要。如果有其他更好的方案,我們也可以一起探討。

原文地址:https://juejin.cn/post/7012825010586779678

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产羞羞视频在线观看免费应用 | 久久久久久久一区二区 | 午夜视频大全 | 国产一区视频在线免费观看 | 一本色道久久综合亚洲精品小说 | av手机在线免费播放 | 中国女警察一级毛片视频 | 草妞视频| 成人做爽爽爽爽免费国产软件 | av色在线观看 | 三级xxxx | 亚州综合 | 成人午夜a | 欧美精品一区二区三区在线 | 91在线视频免费观看 | 欧美一级淫片007 | 亚洲精品一区二区三区大胸 | 热99在线视频 | 亚洲5区| 国产精品视频一区二区三区四 | 午夜久 | 成人毛片一区 | 亚洲成人免费网站 | 欧美黄色一级带 | 亚洲网站免费看 | 91九色网 | 91精品国产一区二区在线观看 | ,欧美特黄特色三级视频在线观看 | 性高湖久久久久久久久aaaaa | 国产视频91在线 | 欧美成人午夜一区二区三区 | 久久精品视频16 | 国产一级免费片 | 凹凸成人精品亚洲精品密奴 | 久久精品一区二区三区国产主播 | 欧美一级aa免费毛片 | 91福利国产在线观一区二区 | 九九热视频在线免费观看 | 蜜桃视频在线观看免费 | 国产在线精品一区二区夜色 | 中午字幕无线码一区2020 |