關(guān)于Android架構(gòu),有這一篇就夠了(干貨總結(jié))

Android開(kāi)發(fā)過(guò)程中拒迅,我們或許見(jiàn)過(guò)這樣的現(xiàn)象:

1. 上帝類(lèi)頻頻出現(xiàn),有些類(lèi)可能包含多個(gè)功能模塊的代碼

2. 臃腫類(lèi)數(shù)不勝數(shù)她倘, 很多類(lèi)里面可能少則1000行璧微,多則幾千行的代碼

3. 不同功能混雜,類(lèi)中包含不同層次的功能硬梁,難以查詢(xún)邏輯主線

4. 無(wú)節(jié)操的代碼重疊


以上現(xiàn)象前硫,在我們開(kāi)發(fā)中,尤其是接手別人代碼時(shí)荧止,會(huì)顯示痛不欲生屹电;那么我們來(lái)看一下上述現(xiàn)象的弊端有哪些 ?

1. 代碼查找 想一下找出需要的代碼跃巡,難危号!哪怕ctrl + F查找,都要分析好久4膳凇4猩!

2. 邏輯交叉混亂 想改什么東西娘香,實(shí)在鼓不起勇氣苍狰!

3. 不同代碼齊聚一堂 鬼才知道添加或修改一個(gè)功能都要改多少地方,何況在不了解需? ? 求的前提下


如果頻頻遇到以上現(xiàn)象烘绽,或許我們就應(yīng)該想了淋昭,到底什么樣的代碼,才是所謂的好代碼呢安接? 有沒(méi)有什么量化的標(biāo)準(zhǔn) 翔忽? 又如何來(lái)很好的避免上述的問(wèn)題 ?

答案是**規(guī)范**與**標(biāo)準(zhǔn)設(shè)計(jì)**

首先談一下規(guī)范,不詳談歇式,不矯情驶悟,建議參考Alibaba推出的Java開(kāi)發(fā)規(guī)范,請(qǐng)走這里:

?阿里巴巴Java開(kāi)發(fā)手冊(cè)

? 這里主要詳談的是設(shè)計(jì)材失,首先來(lái)談一下開(kāi)發(fā)出高內(nèi)聚痕鳍,低耦合,層次分明龙巨,可讀性高的代碼笼呆,需要怎么做 ?

? **1. 分清代碼職能**

? 想要添加一段代碼旨别,首先必須明確這段代碼是用來(lái)做什么诗赌, 這段代碼的功能是什么類(lèi)型的功能 ? 這是一段高度反映業(yè)務(wù)的代碼秸弛?或者是可復(fù)用型的獨(dú)立業(yè)務(wù)功能代碼铭若?又或是與業(yè)務(wù)完全獨(dú)立的常規(guī)輔助類(lèi)型的代碼? 只有明晰了這段代碼的功能與類(lèi)型递览,才能映射出更好的設(shè)計(jì)奥喻。

? **2. 初步劃分模塊**

? 模塊劃分,是系統(tǒng)源碼合理劃分的最有效的途徑之一非迹。但模塊的劃分不是必須的,項(xiàng)目越大纯趋,模塊劃分帶來(lái)的益處越大憎兽;同時(shí)關(guān)注點(diǎn)的劃分也越難。小規(guī)模的項(xiàng)目吵冒,完全可以越過(guò)這一步纯命。

? **3. 初步層次劃分**

? 如果說(shuō),模塊的劃分可以把一個(gè)大的系統(tǒng)有效地劃分為幾個(gè)子系統(tǒng)痹栖;那么針對(duì)不同的子系統(tǒng)亿汞,同樣包含有大量的代碼;因此層次劃分的重要性就不言而喻了揪阿;至于這個(gè)的使用疗我,根據(jù)業(yè)務(wù)進(jìn)行自我分析判斷;一般而言南捂,層次劃分是必要的吴裤,如當(dāng)前流行的MVC, MVP, MVVM等框架

? **4. 功能屬性劃分**

? 和1類(lèi)似,我們需要明白一點(diǎn)溺健,我們的代碼有幾種類(lèi)型麦牺? 總體來(lái)區(qū)分,分為Common與Business;我感覺(jué)Business下還可以進(jìn)行劃分,有些Business是需要復(fù)用剖膳,不同模塊都需要的魏颓, 我稱(chēng)之為**弱業(yè)務(wù)型**;有些Business代碼沒(méi)法重用吱晒,我稱(chēng)之為**強(qiáng)業(yè)務(wù)型**甸饱。因此,我的功能劃分包括: **通用型**枕荞, **弱業(yè)務(wù)型**以及**強(qiáng)業(yè)務(wù)型**柜候。

? **5. 單一職責(zé)原則**

? 單一職責(zé)原則,作為面向?qū)ο蟮?大設(shè)計(jì)原則之一躏精,極大的保證了不會(huì)產(chǎn)生邏輯交叉混亂與上帝類(lèi)渣刷。也是日常開(kāi)發(fā)中必須遵守的原則。在阿里巴巴的**《Java開(kāi)發(fā)手冊(cè)》**中矗烛,也提到了這點(diǎn)辅柴,概括來(lái)說(shuō),就是保證大到每一個(gè)子系統(tǒng)瞭吃,每一個(gè)模塊碌嘀,每一個(gè)分包,小到每一個(gè)類(lèi)歪架,每一個(gè)方法都僅執(zhí)行單一的功能股冗;這個(gè)功能也就是關(guān)注點(diǎn)的劃分,需要根據(jù)開(kāi)發(fā)經(jīng)驗(yàn)來(lái)區(qū)分和蚪,模塊的劃分與方法的劃分必然是不同的止状,而且相去甚遠(yuǎn)。

? **6.? 復(fù)用性與擴(kuò)展性**

? 代碼復(fù)用性攒霹, 相信每一個(gè)人都對(duì)這個(gè)原則有深刻的理解怯疤;復(fù)用性可以極大的提高開(kāi)發(fā)效率, 當(dāng)然必須要配合擴(kuò)展性催束,才能更好的達(dá)到目的集峦。擴(kuò)展性越強(qiáng),復(fù)用范圍就越廣抠刺,該模塊或方法就越具有原子性塔淤。

? **7. 封裝性**

? 在一個(gè)頁(yè)面中,我們可能需要實(shí)現(xiàn)形形色色的需求速妖;如果把這些需求都放在Activity中凯沪,那么可能最后Activity的規(guī)模就可想而知了;除了通過(guò)分層把不屬于Activity的邏輯劃分出去(如MVP中將邏輯放到了P),余下一些的View實(shí)現(xiàn)买优,也需要大量的代碼來(lái)構(gòu)建妨马;這時(shí)候我們可以再次劃分不同的模塊挺举,如TitleBar我們可以根據(jù)業(yè)務(wù)定義自己的TitleBar, 只暴露一些基本的配置,如setTitle()等烘跺;然而有時(shí)TitleBar中也會(huì)包含大量的業(yè)務(wù)邏輯湘纵,這時(shí)我們可以在TitleBar UI層封裝的基礎(chǔ)上,加入一個(gè)TitleBarDao來(lái)處理TitleBar相關(guān)的實(shí)現(xiàn)滤淳,將這塊邏輯繼續(xù)分發(fā)到TitleBarDao中梧喷。


? ? 以上回答了如何更好的設(shè)計(jì)一段代碼,才能更好的保證其邏輯層次的清晰脖咐, 解耦性以及可讀性铺敌,都是個(gè)人愚見(jiàn);代碼設(shè)計(jì)是根據(jù)不同業(yè)務(wù)屁擅,不同規(guī)模進(jìn)行合時(shí)宜的設(shè)計(jì)偿凭,萬(wàn)不可為了設(shè)計(jì)而造成過(guò)度設(shè)計(jì)。設(shè)計(jì)的目的是提高開(kāi)發(fā)效率派歌,提高維護(hù)與測(cè)試效率弯囊。說(shuō)了這么多,如何來(lái)實(shí)現(xiàn)呢 胶果? 以下是一些簡(jiǎn)單的實(shí)例匾嘱。


? 1) 添加一個(gè)View,View顯示的寬度是屏幕的3/4

? ? View targetView;

? ? LayoutParams lp = targetView.getLayoutParams();

? ? lp = 3 * ...獲取屏幕寬度 / 4;

? ? targetView.setLayoutParams(lp);

? 以上這段代碼早抠,很簡(jiǎn)單霎烙,相信很多人也寫(xiě)過(guò);這段代碼首先我們分析功能實(shí)現(xiàn): View寬度的設(shè)計(jì) 和屏幕寬度獲取; 這是一段通用型的代碼蕊连,因此我們可以放在通用層中吼过,方法內(nèi)部包含屏幕寬度獲取的實(shí)現(xiàn),因此根據(jù)單一職責(zé)原則咪奖,我們可以將之抽取出來(lái)。

? 2) string, dimen, style文件

? 這些文件的使用酱床,就是為了將文本, 尺寸, 樣式等抽取出來(lái)羊赵,實(shí)現(xiàn)單一的目的。

? 3) 組件化扇谣,插件化

? 這兩種架構(gòu)方式是大系統(tǒng)規(guī)模的代碼廣義層面的架構(gòu)方式昧捷,將一個(gè)大系統(tǒng)分為若干子系統(tǒng),子模塊來(lái)管理罐寨;

? 4) MVC, MVP, MVVM

? 這些架構(gòu)方式靡挥,則屬于從小的層級(jí)進(jìn)行代碼分層劃分,劃分為不同的層次鸯绿,每個(gè)層次實(shí)現(xiàn)單一職責(zé)跋破。


說(shuō)了這么多簸淀,代碼架構(gòu)的目的是什么?

1. 解耦

2. 復(fù)用

3. 可讀性

4. 健壯性

5. 提高并行開(kāi)發(fā)效率


最近出了很多架構(gòu)思想毒返,無(wú)論是最初的MVC, 還是近幾年風(fēng)頭極盛的MVP, Google推出的MVVM,還是系統(tǒng)層面的組件化租幕,模塊化,插件化拧簸;最終遵循的架構(gòu)原則無(wú)非就是三點(diǎn):

1. 橫向劃分模塊

2. 縱向劃分層次

3. 解耦通信


1. 橫向分塊

一個(gè)大的項(xiàng)目劲绪,代碼量是極大的,甚至達(dá)到1G以上盆赤;這時(shí)必須先以大的層級(jí)進(jìn)行劃分贾富,才能有效達(dá)到分離的目的。現(xiàn)在流行的模塊化思想便有了用武之地牺六;模塊化思想主張將一個(gè)系統(tǒng)橫向切分為不同的子系統(tǒng)或者可以稱(chēng)之為模塊颤枪,根據(jù)業(yè)務(wù)與開(kāi)發(fā)需要將工程劃分為Common模塊, Business-01模塊兔乞, Business-02模塊... 等汇鞭,同時(shí)不同的模塊之間從大的層級(jí)實(shí)現(xiàn)職責(zé)單一原則。

2. 模塊之間解耦

?一個(gè)系統(tǒng)劃分為若干子系統(tǒng)庸追,模塊后霍骄,不同的模塊之間存在交叉通信是必然的;那么如何實(shí)現(xiàn)模塊之間解耦呢淡溯?

?組件化的解耦**思路是實(shí)現(xiàn)一套注冊(cè)路由機(jī)制读整,根據(jù)一套統(tǒng)一的注冊(cè)路由系統(tǒng)來(lái)統(tǒng)一實(shí)現(xiàn)跨組件通信,當(dāng)前比較流程的框架有ActivityRouter,? ?ARouter等

插件化的解耦**則直接通過(guò)Android系統(tǒng)提供的Binder機(jī)制來(lái)進(jìn)行

3. 縱向分層

從系統(tǒng)層級(jí)做了模塊劃分后咱娶,每個(gè)模塊必然也需要自己的架構(gòu)米间,這時(shí)候就需要使用分層的思想了,也就是要說(shuō)的縱向分層策略膘侮。MVC, MVP, MVVM屈糊,F(xiàn)lutter這些設(shè)計(jì)則使用了縱向分層的思想;它們分別將一段代碼或一個(gè)頁(yè)面劃分為3個(gè)層級(jí):

Model層:? ? ? 處理數(shù)據(jù)

View層:? ? ? 處理UI顯示

MVC的Controller, MVP的Presenter, Flutter的Store? ? ?則處理主要邏輯

經(jīng)以上劃分后琼了,數(shù)據(jù)處理逻锐, Ui顯示, 邏輯處理都放到了各自的層進(jìn)行處理雕薪,每個(gè)層僅執(zhí)行本層應(yīng)該做的操作昧诱。分層后,代碼已經(jīng)做到了結(jié)構(gòu)清晰所袁,盡可能的解耦盏档, 易于理解維護(hù)。不過(guò)燥爷,在開(kāi)發(fā)中蜈亩,Model返回的數(shù)據(jù)懦窘,不一定是我們想要的格式; 而且將異步放到Model層勺拣,則Model除了處理數(shù)據(jù)以外奶赠,還要進(jìn)行不同的Async處理。在以上想法下药有,我們可以繼續(xù)劃分:

Model層:? ? 處理數(shù)據(jù)(請(qǐng)求毅戈, 數(shù)據(jù)庫(kù), 緩存等)

Work層:? ? ? 處理異步相關(guān)

Presenter層:? 處理核心控制邏輯

Converter層:? 數(shù)據(jù)轉(zhuǎn)化層 將Model數(shù)據(jù)轉(zhuǎn)化為UI需要的格式

4. 層次間解耦

根據(jù)CleanArchitecture原則愤惰,采用圓蔥形式的分層與解耦策略苇经,因此在設(shè)計(jì)時(shí)注意兩點(diǎn):

1) 明確的層次限定

2) 禁止跨層次調(diào)用

3) 從內(nèi)到外單向調(diào)用

根據(jù)洋蔥結(jié)構(gòu),由內(nèi)到外我們可以得到Model -> Work -> Converter -> Presenter -> UI;在調(diào)用時(shí)宦言,某層只能調(diào)用向內(nèi)的鄰接層扇单,如Presenter只能調(diào)用Work層(存在異步操作時(shí))或Model層(無(wú)異步操作,甚至無(wú)異步操作也可以在Work中封裝一層)奠旺,而不能出現(xiàn)Model層調(diào)用Presenter層的現(xiàn)象蜘澜;相同的,UI層只能調(diào)用Presenter層响疚,而不能跨層調(diào)用Model層鄙信;Converter作為外圍輔助層,不直接參與洋蔥結(jié)構(gòu)


層通信方式

層與層之間的通信忿晕,必然不能通過(guò)直接調(diào)用的方式(特別是View層與Presenter層)装诡,我們可以參考MVP模式中的**接口通信方式**或者Flutter模式中的**Event路由模式**來(lái)實(shí)現(xiàn)。

以登錄功能為例践盼,我們需要以下功能

參數(shù)校驗(yàn)

加載

登錄請(qǐng)求

返回處理

取消加載

顯示結(jié)果

參數(shù)校驗(yàn)鸦采, 參數(shù)的具體信息來(lái)自View層,但是其本身功能為邏輯處理咕幻,因此適合在Presenter層

加載渔伯, 取消加載 涉及到Activity Context來(lái)加載Dialog,因此適合在View層

登錄請(qǐng)求, 毫無(wú)爭(zhēng)議放在Model與Work層肄程,如有參數(shù)轉(zhuǎn)化锣吼,需要加入Converter層

返回處理, 毫無(wú)爭(zhēng)議放在Presenter層

顯示結(jié)果绷耍, 涉及到Toast顯示以及提示,必然在View層

有些實(shí)現(xiàn)可以涉及Context且本身屬于Presenter處理鲜侥,不好區(qū)分褂始;因此建議通過(guò)Context類(lèi)型區(qū)分, 涉及必須使用Activity Context如Toast, Dialog, PopupWindow則在View層描函, AplicationContext亦可的則可以放在Presenter層崎苗。

本篇文章從理論方面講解了Android架構(gòu)一些常用知識(shí)與理念狐粱,且純屬個(gè)人愚見(jiàn),有爭(zhēng)議者可提出一并討論胆数;目的就是找到一個(gè)可以合理解決大部分問(wèn)題且適合移動(dòng)端的開(kāi)發(fā)架構(gòu)肌蜻。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市必尼,隨后出現(xiàn)的幾起案子蒋搜,更是在濱河造成了極大的恐慌,老刑警劉巖判莉,帶你破解...
    沈念sama閱讀 216,744評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件豆挽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡券盅,警方通過(guò)查閱死者的電腦和手機(jī)帮哈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,505評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)锰镀,“玉大人娘侍,你說(shuō)我怎么就攤上這事∮韭” “怎么了憾筏?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,105評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)胡桃。 經(jīng)常有香客問(wèn)我踩叭,道長(zhǎng),這世上最難降的妖魔是什么翠胰? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,242評(píng)論 1 292
  • 正文 為了忘掉前任容贝,我火速辦了婚禮,結(jié)果婚禮上之景,老公的妹妹穿的比我還像新娘斤富。我一直安慰自己,他們只是感情好锻狗,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,269評(píng)論 6 389
  • 文/花漫 我一把揭開(kāi)白布满力。 她就那樣靜靜地躺著,像睡著了一般轻纪。 火紅的嫁衣襯著肌膚如雪油额。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,215評(píng)論 1 299
  • 那天刻帚,我揣著相機(jī)與錄音潦嘶,去河邊找鬼。 笑死崇众,一個(gè)胖子當(dāng)著我的面吹牛掂僵,可吹牛的內(nèi)容都是我干的航厚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,096評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼锰蓬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼幔睬!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起芹扭,我...
    開(kāi)封第一講書(shū)人閱讀 38,939評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤麻顶,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后冯勉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體澈蚌,經(jīng)...
    沈念sama閱讀 45,354評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,573評(píng)論 2 333
  • 正文 我和宋清朗相戀三年灼狰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宛瞄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,745評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡交胚,死狀恐怖份汗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蝴簇,我是刑警寧澤杯活,帶...
    沈念sama閱讀 35,448評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站熬词,受9級(jí)特大地震影響旁钧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜互拾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,048評(píng)論 3 327
  • 文/蒙蒙 一歪今、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧颜矿,春花似錦寄猩、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,683評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至箍铭,卻和暖如春泊柬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背诈火。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,838評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工兽赁, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,776評(píng)論 2 369
  • 正文 我出身青樓闸氮,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親教沾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蒲跨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,652評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容