組件化框架 CC 的源碼解讀

概述

CC 框架是一個(gè)面向協(xié)議的組件化框架,相較于其他面向接口和數(shù)據(jù)結(jié)構(gòu)的組件化框架(得到的框架等),面向協(xié)議的意思是通過開發(fā)者自己定義 ActionName 和數(shù)據(jù) Map 等來(lái)進(jìn)行調(diào)用。因此不需要開發(fā)者再重新定義清晰的接口,而是將這個(gè)調(diào)用轉(zhuǎn)變?yōu)閰f(xié)議,因此能夠提供跨平臺(tái)的功能。

同步調(diào)用

CCResult result = CC.obtainBuilder(COMPONENT_NAME_A)
.setActionName("getInfo")
.build()
.call();

異步調(diào)用

CC.obtainBuilder("demo.lifecycle")
.build()
.callAsyncCallbackOnMainThread(printResultCallback);

調(diào)用時(shí)序圖

點(diǎn)擊查看原圖,可看到清晰的時(shí)序圖

CC框架時(shí)序圖.png

代碼依賴隔離

CC 通過編譯的手段實(shí)現(xiàn)代碼隔離。在主工程的 gradle 中,通過如下語(yǔ)句將各個(gè)組件編譯進(jìn)來(lái):

addComponent 'demo_component_a'
addComponent 'demo_component_kt'
addComponent 'demo_component_jsbridge'

addComponent 是一個(gè)自定義的 lamda 表達(dá)式,源碼在 cc-settings.gradle 中。

  1. 通過過濾篩選出 assembleinstall 的 task,表明此刻進(jìn)行的 task 是生成 apk 的 task(而不是 sync 之類的)
  2. addComponent 替換為 apicompile

通過 addComponent 就實(shí)現(xiàn)了編寫代碼階段不能隨意使用其他模塊的代碼和資源,在編譯時(shí)再換成依賴,實(shí)現(xiàn)代碼隔離

編譯時(shí)依賴注入

CC 通過編譯的手段實(shí)現(xiàn)依賴注入。在主工程的 cc-settings-demo.gradle 中,通過如下語(yǔ)句將實(shí)例編譯階段注入:

ccregister.registerInfo.add([
//在自動(dòng)注冊(cè)組件的基礎(chǔ)上增加:自動(dòng)注冊(cè)組件B的processor
'scanInterface'             : 'com.billy.cc.demo.component.b.processor.IActionProcessor'
, 'codeInsertToClassName'   : 'com.billy.cc.demo.component.b.ComponentB'
, 'codeInsertToMethodName'  : 'initProcessors'
, 'registerMethodName'      : 'add'
])

ComponentB 中我們可以看到:

private void initProcessors() {
}

private void add(IActionProcessor processor) {
    map.put(processor.getActionName(), processor);
}

initProcessors() 方法中沒有任何代碼。add(IActionProcessor processor) 方法接收一個(gè)實(shí)現(xiàn)了 IActionProcessor 接口的實(shí)例。編譯后的代碼如下:

Dependency Inject.png

可以看到編譯后,initProcessors() 方法中注入了 add() 方法,并且傳入了各個(gè) Processor 的實(shí)例。

實(shí)踐

我們可以運(yùn)用代碼隔離和依賴注入來(lái)實(shí)現(xiàn)模塊的完全解耦。

  • 所有模塊相互之間不可見,編譯 apk 時(shí),才打包進(jìn) apk
  • 編寫代碼階段不可見的模塊之間如何進(jìn)行通信呢?在最底層模塊實(shí)現(xiàn)一個(gè)類,像 ComponentB 中一樣持有一個(gè) 類名 - 實(shí)例 的 map。編寫代碼階段,一個(gè)模塊需要與另個(gè)一個(gè)模塊通信時(shí),就從這個(gè) map 中取出另一個(gè)模塊的 interface,面向接口進(jìn)行通信。打包時(shí),通過依賴注入將各個(gè)模塊的實(shí)例加入到 map 中,這樣運(yùn)行時(shí)就是各個(gè)模塊的實(shí)例了。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容