Android元件化開發實踐(三):元件開發規範
不以規矩,不成方圓。特別是多人協作開發時,如果沒有統一的開發規範,勢必會造成各種混亂。在實際開發中,常常會碰到的問題有:
往往單獨的元件工程執行良好,但是整合到殼工程時就是不行,所以我們必須要嚴格遵守規範,儘可能減少這種問題的出現。以下是我在實際開發中採用的一些步驟規範:
1. 新建元件工程
我的每個元件都是一個單獨的小工程,而不是像其他的方案那樣,只有一個主工程,每個元件只是工程裡的一個module,這種方式實質上還是單一工程模式。這樣在程式碼許可權管控,元件職責劃分上就很明確了,每個工程是一個元件,每個元件有一個owner(也就是負責人)。
開啟Android Studio(目前只採用該IDE來開發,其他IDE不考慮),點選"File -> New -> New Project...",全新建立一個新的工程,工程名字以及包名根據實際業務來定。
2. 新建module
在剛建立好的工程中,點選"File -> New -> New Module... -> Android Library",建立一個新的library module,接下來我們所有的元件業務程式碼都將在該module下面開發。

如圖所示,我們所有的元件工程都包含2個module,一個是app,一個是library。在library裡開發真正的業務功能,在app裡只是一個元件的入口,或者是一些demo測試程式碼。
library module的包名設定規則:應用包名+ "." + 業務模組名,假設你的應用包名為com.ali.app,你要開發的業務元件為使用者個人中心,則你的包名可定義為:com.ali.app.userinfo。注意不要與應用以及其他業務元件的包名發生衝突,如果你的團隊足夠大,甚至是跨業務部門,則元件包名的命名需要格外慎重,你可以加上你部門的代號,這樣別人在使用該元件時,一眼就能知道該元件是誰誰誰開發的。
3. 資源名命名規則
所有資原始檔的命名都需要以業務模組名為字首,注意不要與其他業務模組字首名衝突。假設我們在開發"登入"相關的業務,業務模組名為"login",則相關資原始檔命名例子:
- layout檔案:login_activity_quicklogin.xml、login_activity_register.xml
- anim檔案:login_slide_in.xml
- mipmap檔案:login_btn_submit.png
- string:<string name="login_submit">提交</string>
包括但不限於以上這些資原始檔,所有資原始檔的命名都必須遵循該規則,否則可能在整合的時候會被衝突掉。當然還有一種方式是在build.gradle檔案新增如下配置:
resourcePrefix "module_login"
這個在打包編譯時會自動為所有資源加上字首,但是不管加不加該配置,還是強烈建議資源命名增加字首。
4. 第三方庫依賴
在我們使用第三方依賴庫時,需要特別注意依賴庫的版本號。如果第三方依賴庫在多個元件中都有使用,考慮將這些第三方依賴下沉到底層元件庫中統一管理,防止版本號衝突。
5. 資料儲存
- 儘量不要使用資料庫來儲存資料,特殊情況除外。某些ORM框架需要資料庫表集中管理,這樣不利於實行業務模組元件化。
- 使用SharedPreferences時,每個業務模組只管理自己模組需要的資料,SharedPreferences 檔名需要通過業務字首來區分 ,防止不同元件間資料發生衝突。
- 當某些資料需要全域性共享時,可以考慮下沉到底層模組。
6. 元件生命週期管理
當業務元件需要在應用的Application.onCreate()裡進行初始化時,我們要在該元件裡引入生命週期管理。
7. 釋出本地maven庫
我的元件都是採用maven進行管理的,在殼工程整合時直接通過maven引用元件。
前期開發測試時,請先在本機發布maven庫,這樣方便隨時修改更新。 在library module的根目錄下新建一個maven_local.gradle檔案:

maven_local.gradle檔案的配置如下:
apply plugin: 'maven' uploadArchives { repositories.mavenDeployer { pom.version = '1.0.0' pom.artifactId = 'loginlocal' pom.groupId = 'com.hjy.app' repository(url: "file:///Users/hjy/.m2/repository/" } }
- version:maven庫的版本號,初始版本都從1.0.0開始;
- groupId:maven庫的組,你自己統一定義;
- artifactId:maven庫的id,通常為業務模組名,為了與遠端庫區分,本地庫請加local字尾;
- repository:其中"file:///Users/hjy/.m2/repository/"替換成自己本機的gradle快取目錄,在mac中gradle的快取目錄路徑為~/.m2/repository/;
在library module的build.gradle裡增加發布指令碼的引用"apply from: './maven_push.gradle'",然後點選"IDE右側Gradle -> Gradle projects -> 業務module -> Tasks -> upload -> uploadArchives",最後會生成並上傳一個本地的maven庫。
在本地測試時,你可以像下面這樣直接引用本地maven元件庫了。
在工程根目錄下的build.gradle裡增加你本地maven庫地址:
allprojects { repositories { maven { url 'file:///Users/syl/.m2/repository/' } } }
然後你就可以直接通過maven引用你的元件庫了:
compile 'com.hjy.app:loginlocal:1.0.0'
8. 釋出遠端maven庫
如果你的元件庫測試通過,最後需要將release版本釋出在遠端maven伺服器上,在殼工程整合時,採用遠端依賴的方式。與釋出本地maven庫相似,在library module的根目錄下新建maven_push.gradle檔案,然後在module的build.gradle裡,將釋出本地maven庫的指令碼切換成"apply from: './maven_push.gradle'"即可。
apply plugin: 'maven' apply plugin: 'signing' configurations { deployerJars } repositories { mavenCentral() } uploadArchives { repositories { mavenDeployer { pom.version = '1.0.0' pom.artifactId = 'login' pom.groupId = 'com.hjy.app' //請改為自己的maven伺服器地址 snapshotRepository(url: 'http://127.0.0.1/nexus/repository/maven-snapshots/') { authentication(userName: '***', password: '***') } repository(url: 'http://127.0.0.1/nexus/repository/maven-releases/') { authentication(userName: '***', password: '***') } } } } // type顯示指定任務型別或任務, 這裡指定要執行Javadoc這個task,這個task在gradle中已經定義 task androidJavadocs(type: Javadoc) { // 設定原始碼所在的位置 source = android.sourceSets.main.java.sourceFiles } // 生成javadoc.jar task androidJavadocsJar(type: Jar) { // 指定文件名稱 classifier = 'javadoc' from androidJavadocs.destinationDir } // 生成sources.jar task androidSourcesJar(type: Jar) { classifier = 'sources' from android.sourceSets.main.java.sourceFiles } // 產生相關配置檔案的任務 artifacts { archives androidSourcesJar archives androidJavadocsJar }
把repository裡的url替換成你自己的maven伺服器地址,使用者名稱密碼換成你自己的maven賬號即可。
9. 文件要求
每個元件都要維護好說明文件,通常都是一個readme檔案。一般包含以下說明:
- 元件的功能介紹;
- 元件怎麼整合,以及注意事項;
- 元件功能使用說明;
- 元件歷史版本記錄;
儘量做到團隊內任何一個成員,通過該文件就能使用元件,而不需要找到元件的開發人員來講解。
10. 元件整合測試
前面說過,有一種元件開發模式,其工程結構如下圖所示:

“Helloworld”是我們的應用殼工程,“ModuleA”、“ModuleB”、“ModuleC”分別是3個元件,有一種做法是通過配置檔案,動態改邊某個Module是library還是application,這樣就可以直接打包除錯執行某個元件(具體做法可以網上搜索)。但是我說過,這樣沒法做到程式碼許可權管控,也沒法做到開發人員職責劃分,每個開發人員可以對任意的元件進行修改,這顯然會造成混亂。所以我摒棄了這種模式,而是把每個元件都分割成單獨的工程,整合測試時,通過maven引用來整合。
前面講過,前期自己整合測試時,先發布本地maven庫,在殼工程整合時如下所示:
//註冊、登入 compile 'com.hjy.app:loginlocal:1.0.0' //使用者中心 compile 'com.hjy.app:userinfolocal:1.0.0' //支付模組 compile 'com.hjy.app:paylocal:1.0.0'
每個元件的id都加了一個local字尾,這是為了區分我們程式碼引用的是本地的maven元件庫,還是遠端的正式maven元件庫。
如果測試時,發現了bug,只需要把元件庫本地重新發布一下,然後殼工程的gradle檔案重新整理同步一下就可,不用去改版本號,因為這只是你本地的庫,不會與別人的發生衝突。
最後測試通過之後,我們會發布到自己的maven伺服器上,這個時候殼工程的build檔案如下所示:
//註冊、登入 compile 'com.hjy.app:login:1.0.0' //使用者中心 compile 'com.hjy.app:userinfo:1.0.0' //支付模組 compile 'com.hjy.app:pay:1.0.0'
注意,這裡元件的id都去掉了local字尾,同時元件的版本號必須每釋出一次升一次級,並做好版本變更記錄。