讀者在閱讀本篇文章時(shí)饲常,建議先看下“插件化”那邊文章介紹的研發(fā)痛點(diǎn)與研發(fā)流程蹲堂。
在插件化那篇文件中,我們介紹了插件化解決了很多痛點(diǎn)問(wèn)題贝淤,很完美的方案柒竞,不管是研發(fā)還是產(chǎn)品都愛(ài)不釋手,但是插件化的實(shí)現(xiàn)并不是這么容易就能應(yīng)用到產(chǎn)品中播聪,還是要折騰折騰的朽基,其次還要看團(tuán)隊(duì)中有沒(méi)有大神級(jí)人物能hold住。在replugin沒(méi)有開(kāi)源之前离陶,我一直沒(méi)有信心插件化可以落戶每個(gè)Android應(yīng)用稼虎,因?yàn)榉€(wěn)定性問(wèn)題是阻礙插件化的最大絆腳石,這么美的東西得不到手枕磁,實(shí)在是讓人懷疑人生渡蜻,隨著replugin的開(kāi)源,世界又變的如此的美好了计济。即便是這樣茸苇,插件化仍然也有一定的門檻,讓一些團(tuán)隊(duì)望而卻步沦寂。但是面臨如此多的問(wèn)題:方法數(shù)限制学密、安裝包體積、團(tuán)隊(duì)耦合嚴(yán)重传藏、編譯打包慢腻暮、靈活性差等等問(wèn)題,該如何解決毯侦? 答案就是組件化哭靖,組件化不能解決以上所有問(wèn)題,但是也能幫助我們解決一些燃眉之急侈离。
組件化不像插件化那樣強(qiáng)大试幽,解決眾多問(wèn)題,但是組件化同樣是一員猛將卦碾,也會(huì)讓人愛(ài)不釋手铺坞。
組件化可以解決以下問(wèn)題:
1.?團(tuán)隊(duì)耦合嚴(yán)重
2.?部分靈活性問(wèn)題
組件化不像插件化那樣解決靈活性問(wèn)題那么徹底起宽,比如:電商應(yīng)用中的不需要安裝即可上線的一些需求,組件化是無(wú)能無(wú)力的济榨。組件化和插件化一樣都具備模塊化的要求坯沪,即我們都會(huì)產(chǎn)生模塊化的倉(cāng)庫(kù),產(chǎn)品可隨意組裝拼接(安裝包體積可控)擒滑,像搭積木一樣靈活腐晾,各組件的實(shí)現(xiàn)在編譯階段任意替換。
3.?調(diào)試定位問(wèn)題慢
分析
與插件化分析思路相同橘忱,將應(yīng)用進(jìn)行拆分分解到不同的組件中赴魁,插件化與組件化在對(duì)業(yè)務(wù)的拆分原則上相同(可參照插件化的分析章節(jié)),各個(gè)插件與組件都盡量走可獨(dú)立運(yùn)行的路線钝诚,而在插件化的開(kāi)發(fā)中,插件化與組件化應(yīng)該是一種并存的狀態(tài)榄棵,并不是所有的業(yè)務(wù)需求都是一個(gè)可獨(dú)立運(yùn)行的單元凝颇,如果你的架構(gòu)足夠細(xì)化,一定會(huì)提煉出很多組件疹鳄,向各個(gè)插件提供支持拧略。通常這種組件不能獨(dú)立運(yùn)行,需要被集成瘪弓,擴(kuò)展或配置之后才可運(yùn)行垫蛆,這種組件可能是業(yè)務(wù)上的,也有可能是技術(shù)上的腺怯。另外袱饭,完成組件化的架構(gòu)之后后續(xù)轉(zhuǎn)移到插件化會(huì)相對(duì)容易很多。
通常組件的拆分呛占,大致見(jiàn)下圖:
什么是組件化虑乖?
個(gè)人總結(jié):組件化是基于模塊化基礎(chǔ)之上,旨在解決開(kāi)發(fā)階段導(dǎo)致團(tuán)隊(duì)耦合嚴(yán)重等問(wèn)題的一種開(kāi)發(fā)模式晾虑。
組件化與插件化的區(qū)別疹味?
我們先看下組件化的研發(fā)流程,組件化的研發(fā)流程可分為兩個(gè)部分:
1.?開(kāi)發(fā)階段
從上圖我們可以清晰的看到帜篇,與插件化的研發(fā)流程上基本相同糙捺,但是大家要注意這僅是“開(kāi)發(fā)階段”,這樣發(fā)布的版本僅是build版本笙隙,只供QA測(cè)試使用洪灯。這樣做的目的僅是為了減少上面提到的在開(kāi)發(fā)階段耦合嚴(yán)重,定位問(wèn)題慢等問(wèn)題逃沿。 由于將整個(gè)應(yīng)用拆分成了若干業(yè)務(wù)模塊婴渡,每個(gè)模塊在開(kāi)發(fā)階段獨(dú)立開(kāi)發(fā)幻锁,打包,測(cè)試边臼,各模塊間通過(guò)接口協(xié)議來(lái)進(jìn)行通信哄尔。當(dāng)某個(gè)模塊無(wú)法向另外一個(gè)模塊提供接口實(shí)現(xiàn)時(shí),則由當(dāng)前模塊團(tuán)隊(duì)提供模擬的接口實(shí)現(xiàn)來(lái)進(jìn)行測(cè)試實(shí)現(xiàn)柠并。
2. 發(fā)布階段
從上圖可以看出岭接,在真正要發(fā)布版本時(shí),流程是不同的臼予,整個(gè)打包發(fā)布流程是串行的鸣戴,各個(gè)組件的負(fù)責(zé)人需要將正式的組件版本發(fā)布到Maven倉(cāng)庫(kù)中,由集成打包測(cè)試服務(wù)器來(lái)進(jìn)行集成打包粘拾,這樣一來(lái)真正發(fā)布的產(chǎn)品是對(duì)所有組件的集成(安裝包體積仍沒(méi)有改善窄锅,同時(shí)面臨升級(jí)轉(zhuǎn)化,流量缰雇,內(nèi)存等問(wèn)題)入偷,而在插件化中任何階段的打包發(fā)布流程都是并行的,并且發(fā)布的產(chǎn)品只包括核心的功能需求(安裝包體積行涤础)疏之,其余均按需下載支持。
通過(guò)上面的描述暇咆,相信讀者對(duì)插件化與組件化區(qū)別有了一定的了解锋爪。
組件化開(kāi)發(fā)中遇到的問(wèn)題?
組件化開(kāi)發(fā)中會(huì)面臨各種各樣的問(wèn)題爸业,相對(duì)插件化好解決一些其骄,我們來(lái)簡(jiǎn)單介紹下相關(guān)問(wèn)題:
1.?Context問(wèn)題
由于每個(gè)組件在開(kāi)發(fā)階段獨(dú)立開(kāi)發(fā),其他組件可能有自己的application沃呢,各自組件都通過(guò)自己的application去獲取context顯然是錯(cuò)誤的年栓,因?yàn)楫?dāng)被打包到一起時(shí),組件內(nèi)的application不會(huì)被做為主Application(不會(huì)被執(zhí)行attach)薄霜,即使組件內(nèi)的application對(duì)象可以創(chuàng)建某抓,但是組件的application不含LoadedApk等信息,不是一個(gè)真正的Context對(duì)象惰瓜。 在組件內(nèi)可通過(guò)ActivityThead#currentThread()#getApplication()來(lái)獲取否副。
2.?Activity跳轉(zhuǎn)問(wèn)題
組件間存在依賴,互相調(diào)用UI的情況是很常見(jiàn)的崎坊,如何調(diào)用备禀?
1)通過(guò)定義不同的action來(lái)實(shí)現(xiàn);
2)通過(guò)在activity中定義schema,host,path也就是uri來(lái)實(shí)現(xiàn)(推薦使用);
3.?View id的問(wèn)題
由于每個(gè)組件在開(kāi)發(fā)時(shí)是獨(dú)立的曲尸,而每個(gè)組件的layout文件中的view的id是通過(guò)@+id/xx來(lái)實(shí)現(xiàn)的赋续,那么在合并時(shí)組件作為lib,在編譯main時(shí)如果使用的是@+id會(huì)重新生成ID這樣會(huì)導(dǎo)致view找不到的問(wèn)題另患,所以需要強(qiáng)制view不能進(jìn)行編譯纽乱,需要在ids.xml和public.xml中進(jìn)行定義。而每個(gè)layout文件則需要使用@id/xx的方式使用昆箕,不要使用+號(hào)鸦列。
4.?資源名稱沖突
由于在最終打包時(shí)會(huì)將A組件中的資源合并到main中進(jìn)行編譯,那么A組件中的資源名稱不允許與main中的資源重名鹏倘,所以每個(gè)組件中的資源前綴需要添加自己組建的名稱薯嗤;
5.在各個(gè)組件開(kāi)發(fā)階段最好使用同uid來(lái)實(shí)現(xiàn)。
6.包重復(fù)加載問(wèn)題(如果我們各個(gè)組件均通過(guò)gradle從maven去獲取纤泵,這個(gè)問(wèn)題gradle會(huì)屏蔽掉)
寫到這里骆姐,不知道讀者是不是已經(jīng)對(duì)組件化有了一些了解。如果讀者在實(shí)現(xiàn)的過(guò)程中有任何問(wèn)題夕吻,我們可以一起討論诲锹。