說說cc組件化

這個的話,我就結合一下組件化的特性,說說cc時如何實現組件化的可以吧。

1,組件化的第一個特性是解偶
我們把業務組件或者基礎組件放到單獨的module,本身組件之間是不會耦合的,但是app模塊需要依賴所有的模塊,如果使用implementation的話,就直接依賴了對應組件,在app模塊中可以直接調用對應模塊的類或者方法。這時的組件化就沒有完成隔離。

cc提供了addComponent dependencymodule 方法,只有當前task是在給當前module集成打包的時候纔會使用implementation去依賴dependencymodule(dependencymodule沒有在localProperties文件中聲明排除),保證了組件化完全隔離。

這裏有一個問題是如何判斷當前task是在給當前module集成打包?
(在gradle文件中)讀取當前task,如果當前任務是ASSEMBLE|(BUILD)|(INSTALL)中的一種,並且前綴是當前module名,則是爲當前module打包。

2,組件化的第二個特性是需要組件module在application和library之間的自動切換
因爲,一方面我們希望每一個組件直接點運行按鈕,就能獨立打包運行,這個時候需要給它應用application插件,
另一方面的化,比如說有兩個module,當moduleA依賴moduleB,給moduleA打包時, moduleB自動變成library被依賴。

如果是手動切換的話,比較繁瑣。這個時候就需要自動切換

cc會給所有的module應用一個插件,在這個插件裏面,可以判斷當前執行的task:

如果當前task是對當前module集成打包或者當前task不是集成打包的task,則應用application插件,否則應用library插件
這樣就保證了
1、 如果當前task是集成打包的task,並且不是爲該module打包,那麼該module是應用的library插件,可以被依賴;
2、如果當前task不是集成打包的task,module默認都是應用的application插件,可以直接運行 )

另外,它還會根據module應用的是application插件還是library插件,使用sourceSets來給module應用不同的menifest文件。如果是application的話,還會把debug目錄的代碼拷貝到正式目錄去,這些debug代碼就可以進行編譯了。

3,組件化的第三個特性是組件之間的通信。
這裏設計到三種情況
第一種是單進程中組件之間進行通信。
第二種是多進程中組件之間進行通信。
第三種是組件跨app中進行通信。

先說一下cc中組件的概念,cc中有一個icomponent的接口,裏面有一個oncall方法,實現這個接口的類就是一個組件,在oncall方法中可以根據功能名稱去實現整個module的功能分發。

cc中,組件之間通信採用了組件總線通信的方式。
cc中有一個組件管理類,在這個類中維護了一個map,記錄的是組件名稱和組件對象的映射。

第一種是單進程中組件之間進行通信情況,如果組件a調用組件b,首先要構建一個cc對象,參數包括被調用組件的名稱,功能名稱(功能名稱是要調用組件的那一個功能),然後去組件管理類的map中根據組件名稱查找到組件對象,然後調用這個組件對象的call方法,在call方法中根據功能名稱去調用組件對應功能。

然後就是多進程中組件通信和跨app通信,實際上跨app也是跨進程。他們的實現原理相同,但是過程有點不同。

先說他們跨進程通信的原理吧。

比如說組件a運行在進程a,組件b運行在進程b。組件a要調用組件b的功能時,必然涉及到跨進程通信。

cc跨進程通信時採用的contenprovider+aidl。

首先一個前提是cc會給所有的進程都種入一個contenprovider。

首先通過contenprovider獲取到組件b進程中的一個remoteservice的binder對象,(這裏的contenprovider對應的uri是它所在進程的進程名稱)然後通過這個binder對象的call方法發起對組件b的調用,參數有兩個,第一個是cc對象,還是包括了組件名和功能名,第二個參數是個binder類型的callback對象,然後在b進程中的
remoteservice的call方法中響應調用,根據傳遞過來的cc對象,構建出一個本地的cc調用流程對組件b進行調用,然後將對應的返回值通過callback傳遞給調用方。

有兩個問題:

1,組件是如何運行在一個進程中的
組件在哪個進程中調用,自然它就是運行在對應進程的,所以說並不是組件一開始就運行在某個進程,而是組件在這個進程中被調用,它才運行在這個進程。

2,contenprovider對應的uri是它所在進程的名稱,那麼如何知道組件在對應的進程名稱?或者說如何知道組件要在哪個進程被調用?

前提:組件註冊,會將組件名和進程名的對應關係記錄在組件管理類的map中。

情況1:同一個app中,查詢這個map,就可以獲取組件對應的進程名稱。

情況2:跨app調用時,調用方沒法直接查詢被調用方的這個map,因爲是兩個app。

跨app調用時,獲取組件對應進程名稱的具體過程是:

1、app啓動時,獲取到手機中所有應用了cc框架的app,以及它對應的包名(這個包名即主進程名)
2、獲取通過ContentProvider獲取這些app主進程中的RemoteCCService。
3、通過主進程的RemoteCCService去查詢對應app中,組件名稱對應進程名稱的map,就可以獲取組件對應的進程名。

如何知道哪些app應用了cc框架?
在cc框架中內置一個RemoteConnectionActivity,並給其指定一個intent-filter,
使用PackageManager去查詢這個activity對應的activityinfo,繼而通過這個ActivityInfo獲取到對應packageName。

另外會通過廣播監聽app的安裝,可直接獲取app對應的包名,通過判斷是否能啓動RemoteConnectionActivity,如果是就是,應用了cc框架。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章