每當(dāng)開(kāi)始做一個(gè)新的APP , 都是喜憂參半 。喜得是對(duì)新的APP充滿期待谴供,希望小成就感块茁。憂的是沒(méi)有一款好的開(kāi)發(fā)框架 ,最后發(fā)展成傳說(shuō)中“爛尾樓” 桂肌。今兒個(gè)看到一片博客感覺(jué)寫(xiě)的思路清晰数焊,言簡(jiǎn)意賅,很實(shí)用崎场,特來(lái)做一下記錄 佩耳。大部分摘自原文章 。
感謝原創(chuàng)作者?https://blog.csdn.net/guiying712/article/details/55213884?谭跨;
一干厚、為什么要組件化? ,對(duì)比一下兩張圖來(lái)說(shuō)
圖一展示沒(méi)有組件化的架構(gòu) 螃宙,全部業(yè)務(wù)包都寫(xiě)在主工程App中 蛮瞄,業(yè)務(wù)包之間通過(guò)文件夾來(lái)區(qū)分 ,隨著業(yè)務(wù)包越來(lái)越多 谆扎,暴露問(wèn)題也會(huì)越來(lái)越多 挂捅,業(yè)務(wù)包你中有我,我中有你 耦合性高堂湖,編譯耗
1闲先、實(shí)際業(yè)務(wù)變化非常快无蜂,但是單一工程的業(yè)務(wù)模塊耦合度太高伺糠,牽一發(fā)而動(dòng)全身;?
2酱讶、對(duì)工程所做的任何修改都必須要編譯整個(gè)工程退盯;
3、功能測(cè)試和系統(tǒng)測(cè)試每次都要進(jìn)行;
4渊迁、團(tuán)隊(duì)協(xié)同開(kāi)發(fā)存在較多的沖突.不得不花費(fèi)更多的時(shí)間去溝通和協(xié)調(diào)慰照,并且在開(kāi)發(fā)過(guò)程中,任何一位成員沒(méi)辦法專注于自己的功能點(diǎn)琉朽,影響開(kāi)發(fā)效率毒租;
5、不能靈活的對(duì)業(yè)務(wù)模塊進(jìn)行配置和組裝箱叁;
為了滿足各個(gè)業(yè)務(wù)模塊的迭代而彼此不受影響墅垮,更好的解決上面這種讓人頭疼的依賴關(guān)系,就需要整改App的架構(gòu)耕漱。
上圖是組件化工程模型算色,為方便理解這張架構(gòu)圖,下面列舉一些組件化工程中用到的名詞的含義:
總的來(lái)說(shuō) 螟够,App的組件化是告別結(jié)構(gòu)臃腫灾梦,降低耦合 ,讓業(yè)務(wù)模塊變成獨(dú)立開(kāi)發(fā)模塊 妓笙。如果要分離可以隨時(shí)打成"arr"包依賴到app殼下邊 若河。在集成模式下,這些業(yè)務(wù)模塊是library 寞宫。開(kāi)發(fā)的時(shí)候(組件模式下)變成application,這個(gè)在gradle.builder配置文件下通過(guò)變量來(lái)控制 萧福。
二、具體方案: 組件模式和集成模式的轉(zhuǎn)換
Android Studio中的Module主要有兩種屬性辈赋,分別為:
1鲫忍、application屬性,可以獨(dú)立運(yùn)行的Android程序钥屈,也就是我們的APP饲窿;(集成模式下)
2.library屬性,不可以獨(dú)立運(yùn)行焕蹄,一般是Android程序依賴的庫(kù)文件逾雄;(組件開(kāi)發(fā)模式下)
不能每次集成和組件開(kāi)發(fā)區(qū)手動(dòng)更改applicaton和library吧 ,要一處改變腻脏,處處生效 鸦泳,設(shè)置java靜態(tài)變量不正好可以實(shí)現(xiàn)嘛。每當(dāng)生成一個(gè)項(xiàng)目 永品,androidstudio的根目錄會(huì)自動(dòng)生成gradle.properties文件 做鹰,而項(xiàng)目中不管是moudle還是app殼任何一個(gè)build.gradle都可以去讀取gradle.properties中配置的常量? ?,gradle.properties只能定義字符串類型 鼎姐。設(shè)置如下
在moudle中設(shè)置如下 : 字符串轉(zhuǎn)boolean
這樣就解決了獨(dú)立開(kāi)發(fā)和集成的問(wèn)題 钾麸。
三更振、集成模式和組件模式下的??AndroidManifest.xml的合并問(wèn)題
因?yàn)樵诮M件模式下開(kāi)發(fā) ,每一個(gè)moudle配置著自己的注冊(cè)清單文件 饭尝,導(dǎo)致各自有各自的啟動(dòng)Activity ,等等一些配置肯腕,這樣在集成模式的時(shí)候,各模塊之間會(huì)起沖突钥平,手動(dòng)改太麻煩 实撒。其實(shí)注冊(cè)清單文件是可以指定文件夾的 ,如下圖
這樣就解決了這個(gè)問(wèn)題 涉瘾。
四知态、全局Application問(wèn)題
每一個(gè)模塊可能或多或少都會(huì)用到Application全局變量 ,如果每一個(gè)模塊都去創(chuàng)建Appication ,那么在集成模式的時(shí)候就會(huì)起沖突(不允許出現(xiàn)多個(gè)Application) ,怎么解決呢立叛,這就涉及到一個(gè)公用的模塊Common組件负敏,在這個(gè)模塊中可以封裝2個(gè)以上模塊都用到的base類,其中就包括BaseApplication 類? ? 秘蛇。Common組件顧名思義就是公用的模塊原在。所以每一個(gè)業(yè)務(wù)模塊都要去依賴Common組件 ,在App啟動(dòng)時(shí)候彤叉,BaseApplication會(huì)被初始化 。另外也可以初始化一些第三方庫(kù)村怪。在組件話開(kāi)發(fā)模式下會(huì)涉及到需要保存登陸返回的token秽浇,否則后續(xù)模塊接口無(wú)法請(qǐng)求解阅。這樣就可以在Application中模擬寫(xiě)登陸接口在跳轉(zhuǎn)到各自模塊股囊。
五馋劈、Library的依賴問(wèn)題
假如A組件依賴了Conmon ,和多媒體第三方組件 卜高,而Common和多媒體組件都依賴了日志組件 题翰,那么問(wèn)題來(lái)了治泥,日志組件會(huì)被重復(fù)依賴嗎檐嚣,答案是不會(huì) 脊奋,在build文件下可以看到病涨,編譯打包的時(shí)候富玷,這些組件都被打包成了arr包 ,然后被殼工程依賴 既穆,在構(gòu)建過(guò)程中Gradle會(huì)自動(dòng)派出重復(fù)的組件arr包赎懦。另外常見(jiàn)的第三方庫(kù)中可能存在v4,v7這種包,而我們的common中也會(huì)存在這種包導(dǎo)致多包重復(fù)加載 幻工,解決辦法 踢除重復(fù)的包 励两,例如踢除V4包
六、組件之間的調(diào)用和通信
這里我將介紹開(kāi)源庫(kù)的“ARouter”?囊颅,有興趣的同學(xué)情直接去ARouter的Github主頁(yè)學(xué)習(xí):ARouter当悔,樓主需要再總結(jié)一下傅瞻,這里先不多說(shuō)了 。
如果組件之間需要傳遞消息盲憎,可以通過(guò)廣播的形式 嗅骄,也可以通過(guò)Eventbus來(lái)實(shí)現(xiàn)。? ?待補(bǔ)充
七焙畔、組件之間的資源文件名字沖突
這種情況不可避免掸读,目前沒(méi)有什么好的方法,只能說(shuō)大家做好協(xié)商宏多,后續(xù)友好的方法會(huì)補(bǔ)上 儿惫。當(dāng)然如果在組件的build.gradle添加如下的代碼:
但是設(shè)置了這個(gè)屬性后有個(gè)問(wèn)題,所有的資源名必須以指定的字符串做前綴伸但,否則會(huì)報(bào)錯(cuò)肾请,而且resourcePrefix這個(gè)值只能限定xml里面的資源,并不能限定圖片資源
八更胖、簡(jiǎn)介App殼的配置
主要就是release和debug中的配置? ?铛铁,mimsdk和targetsdk版本的配置統(tǒng)一 。dependencies中配置isMoudle變量組件開(kāi)發(fā)模式下和集成模式下的依賴項(xiàng)却妨。
九饵逐、總結(jié)一下業(yè)務(wù)組件和Main組件之間 。
業(yè)務(wù)組件就是根據(jù)業(yè)務(wù)邏輯的不同拆分出來(lái)的組件彪标,業(yè)務(wù)組件的特征如下:
1倍权、業(yè)務(wù)組件中要有兩張AndroidManifest.xml,分別對(duì)應(yīng)組件開(kāi)發(fā)模式和集成開(kāi)發(fā)模式捞烟,這兩張表的區(qū)別請(qǐng)查看 組件之間AndroidManifest合并問(wèn)題 小節(jié)薄声。? ? 查看第三小節(jié)
2、業(yè)務(wù)組件在集成模式下是不能有自己的Application的题画,但在組件開(kāi)發(fā)模式下又必須實(shí)現(xiàn)自己的Application并且要繼承自Common組件的BaseApplication默辨,并且這個(gè)Application不能被業(yè)務(wù)組件中的代碼引用,因?yàn)樗墓δ芫褪菫榱耸箻I(yè)務(wù)組件從BaseApplication中獲取的全局Context生效苍息,還有初始化數(shù)據(jù)之用缩幸。? ? ?查看第四小節(jié)
3、業(yè)務(wù)組件有debug文件夾竞思,這個(gè)文件夾在集成模式下會(huì)從業(yè)務(wù)組件的代碼中排除掉桌粉,所以debug文件夾中的類不能被業(yè)務(wù)組件強(qiáng)引用,例如組件模式下的 Application 就是置于這個(gè)文件夾中衙四,還有組件模式下開(kāi)發(fā)給目標(biāo) Activity 傳遞參數(shù)的用的 launch Activity 也應(yīng)該置于 debug 文件夾中铃肯;? ? 查看下圖12
4、業(yè)務(wù)組件必須在自己的 Java文件夾中創(chuàng)建業(yè)務(wù)組件聲明類传蹈,以使 app殼工程 中的 應(yīng)用Application能夠引用押逼,實(shí)現(xiàn)組件跳轉(zhuǎn)步藕,具體請(qǐng)查看 組件之間調(diào)用和通信 小節(jié);? ? ?查看 ARouter路由的使用
5挑格、業(yè)務(wù)組件必須在自己的 build.gradle 中根據(jù) isModule 值的不同改變自己的屬性咙冗,在組件模式下是:com.android.application,而在集成模式下com.android.library漂彤;同時(shí)還需要在build.gradle配置資源文件雾消,如 指定不同開(kāi)發(fā)模式下的AndroidManifest.xml文件路徑,排除debug文件夾等挫望;業(yè)務(wù)組件還必須在dependencies中依賴Common組件立润,并且引入ActivityRouter的注解處理器annotationProcessor,以及依賴其他用到的功能組件媳板。查看第二小節(jié)
下邊是業(yè)務(wù)組件的配置? ?桑腮,在sourceSet中過(guò)濾掉集成模式下所有debug文件 ,主要是在組件開(kāi)發(fā)模式下蛉幸,要設(shè)置當(dāng)前的組件Application和lunchActivity在debug文件夾下? 破讨,繼承Common組件下的Application ,實(shí)現(xiàn)調(diào)用全局的Context .如上邊3所說(shuō)
debug目錄如下圖 :
十、組件化項(xiàng)目的混淆方案
組件化項(xiàng)目的Java代碼混淆方案采用在集成模式下集中在app殼工程中混淆奕纫,各個(gè)業(yè)務(wù)組件不配置混淆文件提陶。集成開(kāi)發(fā)模式下在app殼工程中build.gradle文件的release構(gòu)建類型中開(kāi)啟混淆屬性,其他buildTypes配置方案跟普通項(xiàng)目保持一致匹层,Java混淆配置文件也放置在app殼工程中隙笆,各個(gè)業(yè)務(wù)組件的混淆配置規(guī)則都應(yīng)該在app殼工程中的混淆配置文件中添加和修改。
之所以不采用在每個(gè)業(yè)務(wù)組件中開(kāi)啟混淆的方案又固,是因?yàn)?組件在集成模式下都被 Gradle 構(gòu)建成了 release 類型的arr包,一旦業(yè)務(wù)組件的代碼被混淆煤率,而這時(shí)候代碼中又出現(xiàn)了bug仰冠,將很難根據(jù)日志找出導(dǎo)致bug的原因;另外每個(gè)業(yè)務(wù)組件中都保留一份混淆配置文件非常不便于修改和管理蝶糯,這也是不推薦在業(yè)務(wù)組件的 build.gradle 文件中配置 buildTypes (構(gòu)建類型)的原因洋只。
十一、組件化工程的gradle.properties文件
在組件化實(shí)施流程中我們了解到gradle.properties有兩個(gè)屬性對(duì)我們非常有用:
1昼捍、在Android項(xiàng)目中的任何一個(gè)build.gradle文件中都可以把gradle.properties中的常量讀取出來(lái)识虚,不管這個(gè)build.gradle是組件的還是整個(gè)項(xiàng)目工程的build.gradle;
2妒茬、gradle.properties中的數(shù)據(jù)類型都是String類型担锤,使用其他數(shù)據(jù)類型需要自行轉(zhuǎn)換;
為了解決上面問(wèn)題就必須將Android項(xiàng)目中 build.gradle 中的 buildToolsVersion 和 GradleBuildTools 版本號(hào)從線上代碼隔離出來(lái)乍钻,保證線上代碼的 buildToolsVersion 和 Gradle Build Tools 版本號(hào)不會(huì)被人為改變肛循。
AndroidStudio本地化配置gradle的buildToolsVersion和gradleBuildTools
buildToolsVersion配置铭腕。
后續(xù)補(bǔ)充demo 。
總結(jié)? :知識(shí)無(wú)價(jià) 多糠,再次感謝原創(chuàng)作者累舷。
組件化相比于單一工程優(yōu)勢(shì)是顯而易見(jiàn)的:
1.組件模式下可以加快編譯速度,提高開(kāi)發(fā)效率夹孔;
2.自由選擇開(kāi)發(fā)框架(MVC /MVP / MVVM /)被盈;
3.方便做單元測(cè)試;? 待補(bǔ)充
4.代碼架構(gòu)更加清晰搭伤,降低項(xiàng)目的維護(hù)難度只怎;
5.適合于團(tuán)隊(duì)開(kāi)發(fā);