1.前言
- 組件化 在Android開(kāi)發(fā)的近幾年來(lái),已經(jīng)由單純編寫(xiě)代碼的概念(工具類(lèi)野芒、第三方組件等等)遷移并應(yīng)用于項(xiàng)目的架構(gòu)上,而在應(yīng)用項(xiàng)目架構(gòu)過(guò)程中又演變出多種不同的實(shí)現(xiàn)方案嘱朽,隨著現(xiàn)代APP應(yīng)用市場(chǎng)的快速發(fā)展栏渺,應(yīng)用開(kāi)發(fā)的時(shí)間、效率凯傲、穩(wěn)定性犬辰、可擴(kuò)展性、靈活性都要體現(xiàn)出高標(biāo)準(zhǔn)的行業(yè)水平冰单,因此開(kāi)發(fā)者就想出把項(xiàng)目劃分多個(gè)模塊幌缝,并且需求滿(mǎn)足協(xié)同與獨(dú)立開(kāi)發(fā),組件化就由此誕生诫欠。
- 文章中實(shí)例 linhaojian的Github
2.目錄
目錄.png
3.組件化發(fā)展史
- 項(xiàng)目架構(gòu)發(fā)展過(guò)程中涵卵,包含非常多種實(shí)現(xiàn)方式,我將它們劃分了三種 傳統(tǒng)荒叼、模塊缘厢、組件:
項(xiàng)目架構(gòu)分類(lèi).png
3.1 傳統(tǒng)化項(xiàng)目結(jié)構(gòu)
傳統(tǒng)化結(jié)構(gòu).png
- 傳統(tǒng)化結(jié)構(gòu):通過(guò) 項(xiàng)目?jī)?nèi)業(yè)務(wù)分包 的方式進(jìn)行開(kāi)發(fā),這種方式 維護(hù)甩挫、擴(kuò)展都非常困難贴硫,并且不方便團(tuán)隊(duì)開(kāi)發(fā),只適應(yīng)小項(xiàng)目伊者。
3.2 模塊化項(xiàng)目結(jié)構(gòu)
模塊化結(jié)構(gòu).png
- 模塊化結(jié)構(gòu):在AndroidStudio 開(kāi)發(fā)工具內(nèi)英遭,通過(guò) 創(chuàng)建module 的方式進(jìn)行劃分不同的業(yè)務(wù)功能,然后在主項(xiàng)目與module 或者 module間構(gòu)建關(guān)聯(lián)(這種關(guān)聯(lián)方式耦合性高)亦渗,當(dāng)module不合理設(shè)置的適合挖诸,會(huì)出現(xiàn)module之間類(lèi)庫(kù)的冗余或者重復(fù)使用。
3.3 組件化項(xiàng)目結(jié)構(gòu)
組件化結(jié)構(gòu).png
- 組件化結(jié)構(gòu):組件化就是在模塊化的思想上優(yōu)化演變出來(lái)法精,在模塊化思想上多律,通過(guò)1.抽出module間公用部分;2.使用路由Router解耦module間的交互搂蜓;3.gradle集成與獨(dú)立配置狼荞;4.代碼與資源的隔離,使得module同時(shí)支持集成開(kāi)發(fā)與獨(dú)立開(kāi)發(fā)帮碰。
4.定義
- 將重復(fù)的代碼進(jìn)行封裝相味,業(yè)務(wù)功能劃分為最小粒子。
5.作用
- 1.復(fù)用代碼殉挽;
- 2.降低業(yè)務(wù)功能間的依賴(lài)或者關(guān)聯(lián)丰涉;
- 3.提供單獨(dú)業(yè)務(wù)運(yùn)行與調(diào)試拓巧;
6.特點(diǎn)
- 1.module具備獨(dú)立性,可單獨(dú)運(yùn)行或調(diào)試一死;
- 2.module間高度解耦肛度,通過(guò)路由交互;
- 3.代碼與資源隔離投慈;
- 4.module劃分盡可能粒子化承耿,便于維護(hù)與復(fù)用;
7.組件化架構(gòu)
- 借助以下的包含實(shí)例的圖逛裤,便于更深入了解 組件化 的架構(gòu)瘩绒;
組件化分層.png - 圖中總共分4層 組件集成、業(yè)務(wù)組件带族、功能組件锁荔、運(yùn)行環(huán)境;
- 組件集成:將所有業(yè)務(wù)組件組合到APP的空殼項(xiàng)目中(空殼項(xiàng)目中只包含啟動(dòng)頁(yè)蝙砌,無(wú)任何業(yè)務(wù)邏輯)阳堕;
- 業(yè)務(wù)組件:將項(xiàng)目按照功能需要?jiǎng)澐至6容^小的module;
- 功能組件:將不同業(yè)務(wù)組件中公用部分封裝為各種類(lèi)庫(kù)择克;
- 運(yùn)行環(huán)境:項(xiàng)目開(kāi)發(fā)中所依賴(lài)的語(yǔ)言庫(kù)或者開(kāi)發(fā)環(huán)境恬总;
- 從圖中可以發(fā)現(xiàn),組件化只存在 垂直關(guān)系肚邢,使各業(yè)務(wù)功能更獨(dú)立與清晰壹堰,更適合現(xiàn)代團(tuán)隊(duì)開(kāi)發(fā)的要求。
8.組件化實(shí)踐
- 下面簡(jiǎn)單配合例子實(shí)踐組件化開(kāi)發(fā)過(guò)程骡湖;
- 項(xiàng)目:類(lèi)似于便利生活的應(yīng)用贱纠;
- 功能:登錄、注冊(cè)响蕴、酒店谆焊、外賣(mài);
-
項(xiàng)目結(jié)構(gòu)如下圖:
例子項(xiàng)目結(jié)構(gòu).png
8.1 base公用
- 1.將module間公用的代碼封裝base的庫(kù)(如:Log庫(kù)浦夷、Base庫(kù)辖试、網(wǎng)絡(luò)請(qǐng)求庫(kù)等等);
-
2.在4個(gè)模塊中添加引用劈狐;
base引用.png
8.2 module獨(dú)立與集成
- 將4個(gè)配置為可以單獨(dú)運(yùn)行或者集成運(yùn)行的狀態(tài):
- 1.打開(kāi)各種module中 gradle.properties文件罐孝,添加如下內(nèi)容:
集成于與獨(dú)立配置1.png - 2.打開(kāi)各種module中 build.gradle文件,添加如下內(nèi)容:
集成于與獨(dú)立配置2.png
集成于與獨(dú)立配置3.png -
3.在module獨(dú)立運(yùn)行時(shí)懈息,需要為其添加對(duì)應(yīng)獨(dú)立運(yùn)行的AndroidManifest.xml文件:
集成于與獨(dú)立配置4.png
- 1.打開(kāi)各種module中 gradle.properties文件罐孝,添加如下內(nèi)容:
-
注:
可以通過(guò)修改isRunAlone的賦值肾档,就能改變module的運(yùn)行狀態(tài),true:可獨(dú)立運(yùn)行辫继,false:集成運(yùn)行怒见。
8.3 多Application初始化
- 因?yàn)閙odule已具備獨(dú)立運(yùn)行開(kāi)發(fā)的特點(diǎn),所以開(kāi)發(fā)過(guò)程中module中就會(huì)按照自己功能內(nèi)需求初始化所需的第三方類(lèi)庫(kù)或者工具庫(kù)姑宽,因此module中就會(huì)存在各自的Application類(lèi)遣耍,那么在集成開(kāi)發(fā)過(guò)程中,我們也需要把module內(nèi)的Application進(jìn)行初始化調(diào)用炮车,不然就會(huì)與獨(dú)立開(kāi)發(fā)不兼容的問(wèn)題舵变,可以通過(guò) 反射 解決:
8.3.1 實(shí)現(xiàn)原理
- 在 主application 中,通過(guò) 反射 把其他module的Application初始化瘦穆。
8.3.2 實(shí)現(xiàn)過(guò)程
* 1.創(chuàng)建一個(gè)抽象BaseApplication纪隙,其他module都繼承于它。
public abstract class BaseApplication extends Application{
public abstract void init(Context context);// 1
@Override
public void onCreate() {
super.onCreate();
// 初始化所有module公用的類(lèi)庫(kù)
initPublic();
// 初始化不同module的Application
init(getApplicationContext());// 2
}
/**
* 初始化Module功能的類(lèi)庫(kù)
*/
public void initPublic(){
ARouter.init(this);
}
}
- 注釋1:提供抽象init方法扛或,使其他module都在init函數(shù)中進(jìn)行初始化绵咱。
- 注釋2:統(tǒng)一和兼容集成與獨(dú)立的2種開(kāi)發(fā)環(huán)境
- 2.讓Login組件繼承BaseApplication
public class LoginAppcation extends BaseApplication {
@Override
public void init(Context context) {
//初始化 login組件 中使用的類(lèi)庫(kù)
// dagger2 、rxjava ....
}
}
* 3.在主項(xiàng)目或者main組件中熙兔,通過(guò)反射進(jìn)行初始化
public class MainAppcation extends BaseApplication {
//module中application類(lèi)的路徑
private static final String[] MODULESLIST =
{"com.lhj.component.login.LoginAppcation"};
@Override
public void init(Context context) {
//初始化 main組件 中所需的類(lèi)庫(kù)
// 初始化其他module的Application
modulesApplicationInit(context);
}
/**
* 通過(guò)反射的方式悲伶,獲取指定Application類(lèi)的實(shí)例,并調(diào)用init函數(shù),解決組件化多appplication獨(dú)立的問(wèn)題
*/
private void modulesApplicationInit(Context context){
for (String moduleImpl : MODULESLIST){
try {
Class<?> clazz = Class.forName(moduleImpl);
Object obj = clazz.newInstance();
if (obj instanceof BaseApplication){
((BaseApplication) obj).init(context);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
}
- 通過(guò) 反射 很好的解決組件獨(dú)立開(kāi)發(fā)的多個(gè)Application初始化問(wèn)題住涉,并且同時(shí)兼容集成開(kāi)發(fā)環(huán)境麸锉,但是反射就存在性能的問(wèn)題,但暫時(shí)沒(méi)有想到一個(gè)更好的解決方案舆声,請(qǐng)各位大神可以評(píng)論指教花沉。
8.4 module間界面的跳轉(zhuǎn)
- 路由Router的誕生就是為了解決module間界面跳轉(zhuǎn)耦合問(wèn)題,在這里我們可以使用阿里的Arouter媳握,如果對(duì)該框架不熟悉碱屁,可以查看我之前的文章Android ARouter:最簡(jiǎn)單&粗暴(使用與原理)講解。
8.5 代碼隔離
- 在集成開(kāi)發(fā)中毙芜,主項(xiàng)目需要對(duì)4個(gè)模塊進(jìn)行引用忽媒,但為了防止在主項(xiàng)目編譯時(shí)引用了其他module內(nèi)的類(lèi)的問(wèn)題,所以需要實(shí)現(xiàn)代碼隔離腋粥,使得真正意義上獨(dú)立晦雨。
-
可以在引用module時(shí),使用以下方式:
代碼隔離.png
8.6 資源隔離
- 在集成開(kāi)發(fā)中隘冲,如果module之間存在資源名字相同的情況時(shí)闹瞧,可能會(huì)影響項(xiàng)目的運(yùn)行或者誤導(dǎo)開(kāi)發(fā)人員,
所以建議為不同module的資源文件添加對(duì)應(yīng)的命名規(guī)則:- 1.xml內(nèi)(string展辞、colors等資源文件)的命名方式可以通過(guò)如下配置方式奥邮;
- 如:將登錄module的xml文件
android {
//...
// 實(shí)現(xiàn)資源隔離
resourcePrefix "login_"
}
* 2. 對(duì)于控件名稱(chēng)與文件名稱(chēng),可根據(jù)自己的喜歡區(qū)分;
8.7 數(shù)據(jù)復(fù)用
- 項(xiàng)目開(kāi)發(fā)過(guò)程中洽腺,經(jīng)常會(huì)出現(xiàn)數(shù)據(jù)需要全局應(yīng)用脚粟,因此在多module間需要實(shí)現(xiàn)數(shù)據(jù)復(fù)用,可以通過(guò)以下方式實(shí)現(xiàn):
- 1.使用Arouter框架中的Provider功能(將復(fù)用的數(shù)據(jù)保存base庫(kù)的Provider中蘸朋,然后通過(guò)Arouter的navigation函數(shù)獲群宋蕖);
- 2.base庫(kù)中藕坯,可以按需添加對(duì)象全局?jǐn)?shù)據(jù)的管理類(lèi)团南。
8.8 資源復(fù)用
- 將可能會(huì)復(fù)用的資源,添加至base庫(kù)中炼彪,防止資源重復(fù)的問(wèn)題吐根。
9.總結(jié)
- 到此,Android項(xiàng)目組件化開(kāi)發(fā)介紹完畢辐马!
- 如果喜歡我的分享拷橘,可以點(diǎn)擊 關(guān)注 或者 贊,你們支持是我分享的最大動(dòng)力 齐疙。
- linhaojian的Github
歡迎關(guān)注linhaojian_CSDN博客或者linhaojian_簡(jiǎn)書(shū)膜楷!
不定期分享關(guān)于安卓開(kāi)發(fā)的干貨。
寫(xiě)技術(shù)文章初心
- 技術(shù)知識(shí)積累
- 技術(shù)知識(shí)鞏固
- 技術(shù)知識(shí)分享
- 技術(shù)知識(shí)交流