一、模塊化淺談
1. Android 模塊化開發(fā)介紹;
模塊化開發(fā)思路就是:?jiǎn)为?dú)開發(fā)每個(gè)模塊,用集成的方式把他們組合起來,就能拼出一個(gè)app。app可以理解成很多功能模塊的組合,而且有些功能模塊是通用的,必備的,像自動(dòng)更新,反饋,推送,都可以提煉成模塊,和搭積木很像,由一個(gè)殼包含很多個(gè)模塊。
2.Android 模塊化開發(fā)的好處;
模塊升級(jí)會(huì)單獨(dú)升級(jí),升級(jí)的時(shí)候往往不只是增加資源,有時(shí)候會(huì)去刪資源,這樣做和其它的模塊的資源不摻乎,我用umeng的自動(dòng)更新sdk時(shí)就需要我連著資源一塊進(jìn)來,加進(jìn)來容易以后不想用umeng的了再挑出去就很費(fèi)事了。再假如push開始用的百度的后來換成極光的,對(duì)app的組合者其實(shí)是不關(guān)心的,對(duì)他影響很小。解耦很好。如果是主力帶實(shí)習(xí)生這種開發(fā)的話,核心代碼就不用和他們分享,讓他們?nèi)プ霆?dú)立的功能,做好直接調(diào)用就行。以后整理代碼,重構(gòu)什么的都只重構(gòu)這個(gè)模塊的代碼,他們不會(huì)不小心改了核心代碼。
二、模塊化開發(fā)的架構(gòu)分層
命名建議:
底層:Library
中間層:Module + 業(yè)務(wù)或功能名字
上層:App + 項(xiàng)目名字
建議分層進(jìn)行
-
底層:包含基礎(chǔ)庫和底層庫
- 基礎(chǔ)庫:
包含所有模塊需要的依賴庫,以及一些工具類,比如封裝了的常用網(wǎng)絡(luò)請(qǐng)求,封裝圖片處理fresco
,數(shù)據(jù)庫相關(guān)等,還包含所有模塊需要的依賴庫; - 底層庫:
主要是使用C/C++開發(fā)的跨平臺(tái)的引擎或者庫,以so的形式存在。例如:游戲引擎cocos2d
- 基礎(chǔ)庫:
-
中間層
首先、分模塊肯定要按照功能分,獨(dú)立的一個(gè)功能,不能雜。比如、更新、登錄、分享、播放,都可以。
其次、我采取aar的形式作為模塊的最小單位,為什么是aar不是jar,更不是library,因?yàn)閖ar不能帶資源只能帶java代碼,library的話太容易被修改了,aar的好處是能帶資源并且是編譯好的,不能被修改。保證了模塊的版本不會(huì)在被別人調(diào)用的時(shí)候隨意修改,如果想修改就要聯(lián)系做aar的人,讓他去升級(jí)aar的版本。
用android studio,打aar用maven;aar其實(shí)就是依賴,只不過之前的依賴都是存到了maven遠(yuǎn)程庫里,自己用的話可以自己建和私有的maven庫,太蠻煩的話可以直接用本地的aar文件做依賴。
-
上層
將所有的業(yè)務(wù)模塊聚合在一起,加上配置,形成主應(yīng)用,一個(gè)模塊化做的好的應(yīng)用,主應(yīng)用應(yīng)該很簡(jiǎn)單,并且非常的穩(wěn)定。
三、如何進(jìn)行Android 模塊化開發(fā)
進(jìn)行Android 模塊化開發(fā)前先復(fù)習(xí)一個(gè)基礎(chǔ)知識(shí),介紹一下 Studio 項(xiàng)目結(jié)構(gòu)。
- MyApplication 整個(gè)項(xiàng)目目錄
- app 項(xiàng)目中app模塊目錄
- settings.gradle 定義項(xiàng)目包含哪些模塊
- app/build/ app模塊build編譯輸出的目錄
- app.iml app模塊的配置文件
- External Libraries 項(xiàng)目依賴的Lib,編譯時(shí)自動(dòng)下載的
可以看出 Studio 新建的項(xiàng)目自身就是一個(gè)模塊化項(xiàng)目,MyApplication 是整個(gè)項(xiàng)目,而app是一個(gè)模塊,所以在后續(xù)自行增加更多的功能模塊。
1.創(chuàng)建 Module 模塊;
將所需的模塊在對(duì)應(yīng)項(xiàng)目的Project
目錄下拷貝出來,粘貼到要開發(fā)的項(xiàng)目的Project
根目錄下即可。也可以直接在project
下新建一個(gè)Module
。
File --> New --> New Module --> Android Library (建議選擇這個(gè)) --> Finish
一個(gè)模塊這樣就創(chuàng)建完成了。默認(rèn)的名字是app
,根據(jù)項(xiàng)目的需要將模塊的名字進(jìn)行修改,直接Refactor > Rename...即可
2.將 Module 模塊引入主項(xiàng)目中;
設(shè)置setting.gradle 中
include ':projectName'
設(shè)置后發(fā)現(xiàn)項(xiàng)目目錄下增加了一個(gè)模塊
對(duì)weather
模塊下的build.gradle
進(jìn)行sync操作后,
藍(lán)色小茶杯變成了小手機(jī)的圖標(biāo)
在主模塊的build.gradle中設(shè)置
dependencies {
...
compile project(':projectName')
...
}
3.模塊中 application 和 library 狀態(tài)切換配置;
<font color=red>組件化不是插件化,插件化是在[運(yùn)行時(shí)],而組件化是在[編譯時(shí)]。插件化是基于多APK,而組件化本質(zhì)上還是只有一個(gè)APK。</font>
-
設(shè)置一個(gè)開關(guān)控制
application
和library
狀態(tài)切換
我們?cè)陂_發(fā)的時(shí)候,Module
如果是一個(gè)庫,會(huì)使用com.android.library
插件,如果是一個(gè)應(yīng)用,則使用com.android.application
插件,接下來根據(jù)這個(gè)變量來進(jìn)行判斷并且實(shí)現(xiàn)狀態(tài)切換。
Project
根目錄下gradle.properties
中設(shè)置變量來控制。asApp=false ...
asApp=false:表示這個(gè)模塊是一個(gè)Module;
asApp=true:表示這個(gè)模塊是一個(gè)app; -
依賴項(xiàng)目中
build.gradle
配置
在模塊的build.gradle
的開頭處設(shè)置。// 開頭處設(shè)置 if (IsBuildModule.toBoolean()) { apply plugin: 'com.android.application' } else { apply plugin: 'com.android.library' } android { ... defaultConfig { // library 下刪除 applicationId if (IsBuildMudle.toBoolean()) { applicationId "com.qsp.weather" } .... } }
-
提供兩套
AndroidManifest.xml
并進(jìn)行動(dòng)態(tài)切換
mainfest文件也需要提供兩套android { ... sourceSets { main { if (IsBuildModule.toBoolean()) { manifest.srcFile 'src/main/buildModule/AndroidManifest.xml' } else { manifest.srcFile 'src/main/buildApp/AndroidManifest.xml' } } } }
-
buildModule 的 AndroidManifest.xml, activity 等在這里可以正常注冊(cè)。這里注冊(cè)后主程序就可以不用寫了寫在哪里都可以。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.qsp.weather"> <application android:allowBackup="true" android:supportsRtl="true"> </application> </manifest>
-
四、Project 中模塊以 aar 方式引入;
模塊化方式分兩種,第一種是以aar的方式引入項(xiàng)目中,因?yàn)橛行┠K在開發(fā)中可能功能不穩(wěn)定或是不成熟,以arr形式引入不方便進(jìn)行修改,所以這時(shí)候就可以以模塊源碼的方式引入。
1.導(dǎo)出 aar;
Android Library項(xiàng)目的gradle腳本在開頭聲明
apply plugin: 'com.android.library'
執(zhí)行./gradlew assembleRelease
然后在build/outputs/aar
文件夾里生成aar文件
2.引用本地的aar;
生成aar之后下一步就是如何引用本地的aar文件?本地的aar文件并沒有像引用jar文件這么簡(jiǎn)單,官方也沒有提供解決方案。好在國外的一些前輩總結(jié)出了方法,下面就以test.aar文件為例來詳述下方法。
1.把a(bǔ)ar文件放在一個(gè)文件目錄內(nèi),比如就放在libs目錄內(nèi)
2.在app的build.gradle文件添加如下內(nèi)容
repositories {
flatDir {
dirs 'libs' //this way we can find the .aar file in libs folder
}
}
3.之后在其他項(xiàng)目中添加一句gradle依賴便方便的引用了該library
dependencies {
compile(name:'test', ext:'aar')
}
五、Android 模塊化開發(fā)過程中遇到的問題
1.資源名沖突;
Android Studio 默認(rèn) library 的所有的 resource 為 public , 所以在模塊化開發(fā)過程中總會(huì)遇到資源沖突問題。列出兩種解決方法。
-
方法一:
保護(hù)某些 resources 不被外部訪問,可以創(chuàng)建res/values/public.xml
,因?yàn)?public 是關(guān)鍵詞,搜易需要用 new file 的方式創(chuàng)建。至少添加一行,為添加的視為 private。<resources> <public name="mylib_app_name" type="string"/> </resources>
-
方法二:
在 library 的 build.gradle 中添加resourcePrefix
, 則所有的資源須以此 prefix 開頭,否則報(bào)錯(cuò)。注意,圖片資源雖然不提示報(bào)錯(cuò)誤,但是也需要修改名字。android { ... buildTypes { ... } resourcePrefix 'my_prefix_' }
2.重復(fù)依賴;
將所有的依賴都寫在library層的module,將所有的依賴同意成一個(gè)入口給上層的app去引用。
3.控制臺(tái)報(bào)錯(cuò)解決;
Error:Module 'qsp_release:libLive:unspecified' depends on one or more Android Libraries but is a jar
報(bào)這個(gè)錯(cuò)誤的場(chǎng)景,Moudle A 的build.gradle
下
apply plugin: 'java'
...
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile project(':library')
...
}
可以看出 Moudle A 是一個(gè)jar形式的依賴模塊,而library
是apply plugin: 'com.android.library'
所以引用報(bào)如上錯(cuò)誤。