初期Android項目構建方式基本爲分層結構設計,因爲初期項目較小這種架構簡單,清晰所以沿用至今。而當項目業務逐漸擴大時發現簡單的分層結構已經沒法知足現有項目架構,尤爲是多人開發時各個業務之間溝通成本成指數上升。 應運而生的模塊化思想誕生,初期你們只是將項目的業務進行簡單拆分紅各個module,以主module去引用子module。java
後來發現這種方式隔絕了子module之間的通訊,且主module只能主動的引用子module,沒法被子module訪問。隨之而來進入主題了--組件間如何去通訊android
目前最經常使用的通訊方式有Event、協議、RPC接口三種主要形式,但實際上都只是協議的一種變形封裝而已。從標題能看出我參考了微信的模塊化通訊我就不墨跡,我更傾向於微信的RPC形式的通訊方式。 緣由有如下幾點:api
方式已經肯定那接下來就是解決實現上的難題,從上述緣由中咱們能夠看到幾個關鍵點:bash
首先咱們來講說如何生成接口aar,你們都知道aar對應的是一個獨立的module,那如何自動生成該module? 從微信的實現上看它是爲setting新增了include_with_api方法,並修改了gradle指向的setting實現類,從而在初始化setting類時自動生成接口module。 因爲我的研究時間有限目前採用取巧方案,在setting.gradle文件中新增include_with_api方法用來自動生成接口module,而build.gradle和AndroidManifest.xml文件皆從實現module中拷貝過來,並修改AndroidManifest.xml中的package以及去掉android:label信息,再去掉原有build.gradle的接口module依賴,從而順利解決接口module生成方式。微信
def include_with_api(def projectName) {
include projectName
String rootDir = rootDir.getAbsolutePath();
String moduleName = ((String) projectName).replace(":", "")
String parentName = moduleName.replace("plugin-", "");
copy() {
from rootDir + '/' + parentName + '/build.gradle'
into rootDir + '/' + moduleName + '/'
filter { line ->
String content = line;
if (content.contains(moduleName)) {
content = "";
}
content
}
}
copy() {
from rootDir + '/' + parentName + '/src/main/AndroidManifest.xml'
into rootDir + '/' + moduleName + '/src/main/'
filter { line ->
String content = line;
content = content.replace("android:label=\"@string/app_name\"", "")
if (content.contains("package=\"")) {
content = content.replace("\">", ".plugin\">")
}
content
}
}
}
複製代碼
再來看下關於接口暴露的問題,其實接口暴露方案主要仍是參考微信只不過中間實現細節是否同樣就不可知了。 下面着重介紹下個人細節實現,從微信方案中能夠看出是將接口文件從.java後綴改爲.api,而後將.api後綴的文件拷貝至接口module中。經過gradle插件來定製依賴配置項compileApi,實現module經過compileApi依賴關聯接口module,在解析中將實現module中接口文件拷貝至接口module並修改後綴名從而經過編譯。架構
Configuration configurationtest = project.configurations.create("compileApi")
configurationtest.canBeResolved = true;
configurationtest.canBeConsumed = true;
configurationtest.setVisible(false)
//當該依賴配置被解析時會執行
configurationtest.allDependencies.all {obj->
moveFile(project, obj.name)
project.dependencies.add("compile", project.project(':' + obj.name))
}
複製代碼
接下來咱們能夠考慮如何註冊以及初始化接口實現類,所謂的註冊也就是如何經過接口找到實現類並隱式實例化。app
@AService("com.netease.add.Add")
public abstract class IAdd extends IService{
abstract int add(int a, int b);
}
public static <T extends IService> void register(Class<T> clazz) {
try {
AService aService = clazz.getAnnotation(AService.class);
if (aService == null) {
return;
}
String clazzName = aService.value();
if (!TextUtils.isEmpty(clazzName)) {
T t = (T) Class.forName(clazzName).newInstance();
ServiceManager.getInstance().put(clazz.getSimpleName(), t);
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
複製代碼
上述只是我對微信模塊化通訊環節的實現,從而打通了整個環路。至於項目的模塊化改造還得依狀況而定,從思惟角度來說要遵循大事化小,若是自己就是個小項目就不必引入繁瑣的模塊化架構。模塊化不僅僅只是說說以及架構環節,還涉及如何劃分模塊邊界等細節問題。 最後但願咱們分享的一點經驗能對你們有些價值。模塊化