最簡單有效的低侵入性的Android元件化方案
本元件化方案已開源在github,歡迎轉載和star。 ofollow,noindex">https://github.com/beyondxia/modules
傳統元件化方案問題
上篇中我們對傳統的元件化方案的實現原理進行了簡單的介紹,以及對其優缺點進行了相應的分析。針對介面通訊機制的方案,有如下缺點:
a、需要提供一個公共的目錄或者公共模組用作為服務層,所有介面檔案和中間共享的檔案都需要手動拷貝至服務層。
b、元件若需要提供服務,除了本身的實現類,還需要提供一個或多箇中間介面檔案,增加了開發量和元件整合的複雜度以及維護成本。
c、由於服務實現類與服務介面存在依賴關係,所以業務方需要實現暴露的介面,並要實現具體需要暴露的業務功能。
d、所有的元件服務的註冊都需要手動進行,增加了開發量與風險。
e、與介面相關的一些中間類(特別model)也需要同步下沉至公共目錄。
優化方案
1. APT生成介面檔案
針對不足點a和b,如果可以自動生成並拷貝介面檔案,那為題就迎刃而解,那該如何做呢?
我們知道,APT(Annotation Processing Tool 的簡稱)可以在程式碼編譯期解析註解,生成新的Java檔案,可以減少手動的程式碼輸入.
本框架就是利用APT進行介面檔案的自動生成。使用者要做的只是給需要暴露的服務以及服務中需要暴露的方法新增相應的註解(@ExportMethod),APT將根據註解自動生成介面。如下圖所示,Message即為元件提供的服務類,IMessage為生成的介面。

image.png
2. javassist修改位元組碼
APT可以生成對外暴露介面,那接下來我們需要做的就是讓業務方實現該介面,並完成真正功能的實現,那又改如何做呢?
其實從程式碼層面看,我們只需要Message類實現IMessage,由於Message在IMessage介面生成前就已經由模組內部實現,所以如果要修改Message,最好的方法還是編譯階段修改Message.class位元組碼。
Javassist 是一個執行位元組碼操作的庫。它可以在一個已經編譯好的類中新增新的方法,成員,或者實現某個介面、繼承某個父類等。
針對不足點c:Javassist剛好可以滿足我們的需求,編譯階段通過修改位元組碼,讓Message實現介面IMessage。這樣就實現了服務類Message與服務介面類IMessage的實現關係。

image.png
這樣還有一個好處:若服務類進行版本升級,框架會通過APT與gradle transform技術可以對服務介面做到靜默自動同步,對元件開發者完全無感知,開發者只需專注於開發自己的元件業務即可。
3. APT完成元件的蒐集和註冊
針對不足點d:框架通過APT技術,對有ExportService註解標識的服務類進行收集,並在框架初始化的時候進行自動註冊,開發者完全不需要參與註冊工作。並且我們根據服務的使用場景以及頻率提供了不同的例項化時機,可根據元件的使用場景在註解上進行相應的配置即可。

image.png
4. 自定義BCDictionary代替傳統Model
針對不足點e:我們不提倡元件間以自定義的model傳輸資料,但傳輸複雜型別的資料型別又是不可避免的,當然可以選擇現有的序列化方式傳輸,如json,但在序列化和反序列化時需要開發者做諸多繁瑣的操作。為此,框架提供了一種簡單易用的的傳輸複雜型別資料型別的方式,極大程度上簡化了序列化與反序列化的操作。
其他問題:
如果元件間因為業務需要,需要共享複雜資料結構,如:

image.png
需要暴露一個自定義view。 從原則上來講,元件化設計不建議元件間共享複雜型別,即使有這類型別,更建議以通用資料下沉至base層的方式。 但是針對一個大型專案做元件化拆分的時候,有時必然要設計這類問題。針對這樣的問題,是需要手動拷貝檔案至服務層。
<strong>通過以上介紹的方案,框架基本上解決了介面通訊方式存在的缺點。大部分工作已經由框架在編譯階段完成,極大的減少了業務接入的成本,對程式碼侵入性極小,使開發者可以專注於元件功能的開發。</strong>