Android MVP設(shè)計(jì)架構(gòu)優(yōu)化(靈活、方便迭代)

本架構(gòu)是通過使用 RxJava + RxAndroid +Retrofit2 + Butterknife搭建的。

寫作目的

隨著項(xiàng)目逐漸壯大,必須有一個(gè)完善的框架作為一個(gè)支撐,不然難以維護(hù)。針對(duì)目前流行的框架,如:MVC,MVP,MVVM,我選擇了 MVP 作為 Android APP 整體架構(gòu)。

下圖為 MVP 架構(gòu)圖:

2EBDB2C6-80DD-4C57-9F53-75ED57D6E04D.png

怕我沒說清楚,再具體一點(diǎn):

168F2A09-4EC1-43C4-8530-F9D751376580.png

一開始,我也只是使用簡單的 MVP 模式(也就是一個(gè) activity 實(shí)現(xiàn)多個(gè) view 接口,同時(shí)一個(gè) activity 包含多個(gè) presenter,一個(gè) presenter 包含多個(gè) model,presenter 包含一個(gè) view。其實(shí)也就是標(biāo)準(zhǔn)型的 MVP 模式)。但是隨著項(xiàng)目逐漸壯大,presenter 里的代碼就越來越多,而且業(yè)務(wù)層代碼也越來越不清晰了。由于我的項(xiàng)目架構(gòu)是使用功能分類的,所以 presenter 也用功能分類,但由于 presenter 只包含一個(gè) view 導(dǎo)致所有需要該 presenter 的 activity 都只能使用同一個(gè) view,這樣 view 的耦合度就很高了。對(duì)于有代碼潔癖的我來說,實(shí)在有點(diǎn)難忍。于是我決定優(yōu)化一下。

在優(yōu)化之前,必須要知道設(shè)計(jì)框架目的是什么,設(shè)計(jì)框架絕對(duì)不能為設(shè)計(jì)而設(shè)計(jì)!

裝逼圖.jpg

設(shè)計(jì)架構(gòu)的目的是什么:
通過設(shè)計(jì)使程序模塊化,做到模塊內(nèi)部的高聚合和模塊之間的低耦合。這樣做的好處是使得程序在開發(fā)的過程中,開發(fā)人員只需要專注于一點(diǎn),提高程序開發(fā)的效率,并且更容易進(jìn)行后續(xù)的測(cè)試以及定位問題。但設(shè)計(jì)不能違背目的,對(duì)于不同量級(jí)的工程,具體架構(gòu)的實(shí)現(xiàn)方式必然是不同的,切忌犯為了設(shè)計(jì)而設(shè)計(jì),為了架構(gòu)而架構(gòu)的毛病。同時(shí)希望設(shè)計(jì)的架構(gòu)能夠模塊化,希望把跟業(yè)務(wù)無關(guān)的東西抽象出來,開發(fā)人員根本只需要寫業(yè)務(wù)代碼就夠了。


整體思想

需要解決的問題:

  • 讓 presenter 更加靈活,可以靈活使用到多個(gè) activity 中。
  • 讓項(xiàng)目業(yè)務(wù)更加清晰,由于產(chǎn)品是迭代開發(fā)的,一般就兩周一個(gè)版本,必須方便迭代。
  • 新增功能模塊必須方便,能形成模版,可以無腦使用。

下面開始介紹優(yōu)化內(nèi)容:
先上一個(gè)圖,作為一個(gè)簡單介紹:

179B9FB5-30F4-4037-A49F-5CE465404620.png

如圖所示,view 的展示仍然由 activity 處理,presenter 仍然是中間人,model 還是業(yè)務(wù)邏輯層。不同的是,Activity 包含的 presenter 有多個(gè),并且是放在 SparseArray 數(shù)組里面的,presenter 里也包含多個(gè) view 和多個(gè) model,也都是放在 SparseArray 數(shù)組里面的。如何獲取具體的 presenter 或者 view、model 呢? 答案是通過 Action. Action 是重點(diǎn)。Action 放的是具體功能包含的操作。Action 從 Activity 傳入到 Presenter,通過 Action 在 Presenter 可以判斷用哪個(gè) View 來展示界面。
我不大會(huì)畫圖,可能大家會(huì)噴我了。

文明圖.jpg

好吧,罵完了,我繼續(xù)裝逼了,舉個(gè)栗子吧:

比如說登錄功能,個(gè)人中心需要登錄、購物車結(jié)算也需要登錄,那么登錄就可以作為一種功能寫一個(gè) Presenter,而個(gè)人中心登錄需要展示登錄成功也需要展示登錄失敗,而購物車結(jié)算也許只需要登錄成功就可以了,而不需要展示登錄失敗,所以我需要有兩個(gè)不同的 View,一個(gè)是用于個(gè)人中心的,一個(gè)用于購物車結(jié)算。Action 怎么設(shè)置呢?就需要根據(jù)這個(gè)登錄功能設(shè)置兩個(gè) Action,因?yàn)槲覀冃枰诘卿?Presenter 里面根據(jù)不同的 Action 來選擇 View。Presenter 在 Activity 初始化的時(shí)候傳進(jìn)去,并且包含展示 View 的接口和 Action,于是 Presenter 就有 Action 了,當(dāng) Action 是來自于個(gè)人中心時(shí),Presenter 就可以根據(jù)個(gè)人中心登錄的 Action 調(diào)用它獨(dú)有的 View 來展示。當(dāng)是來自購物車結(jié)算頁面時(shí),也可以根據(jù) Action 來調(diào)用它獨(dú)有的 View。這樣就讓 Presenter 靈活了。

不過馬上有人會(huì)有問題了,這樣 Action 會(huì)不會(huì)很混亂?
是的,如果沒有統(tǒng)一管理的話確實(shí)會(huì)很混亂,這就是設(shè)計(jì) Contract 和 BaseAction 的理由。Contract 跟 Presenter 是成雙成對(duì)的。一個(gè) Presenter 對(duì)應(yīng)了一個(gè) Contract,Contract 里面就把 View、Presenter、Action 綁架到一起了,這樣便于管理同時(shí)便于修改。

我還害怕我沒說清楚,下面給部分代碼便于理解:

例如在登錄功能中,用戶中心登錄的操作。整體使用功能分類,如圖所示:

14B84020-ECC2-48F6-8D19-0D9D6A3899E1.png

user 代表用戶中心,(原諒我英語不好,只能寫個(gè)簡單的單詞)
可見我這是通過功能分類。首先沖 Activity 來。

在 LoginActivity 初始化的時(shí)候,將所需要的 Presenter 都加入進(jìn)來,并且傳入 Action 將他們連接起來。如下圖:

EEFCE22E-2E10-465C-BD25-FE30337B4A9A.png

這樣業(yè)務(wù)的 Activity 里面已經(jīng)木有了 Presenter, addPresenter 是來自基類(BaseActivity)的方法,這樣的好處在于我們可以統(tǒng)一管理 Presenter。

用戶登錄的 Action 可以這樣寫:

54F802E8-41B6-4AF0-9F29-FE7332653A14.png

因?yàn)榭赡苡袃蓚€(gè) Activity 需要登錄功能,而需要展示不同的界面。所以寫了兩個(gè) Action。

像以前一樣 LoginActivity 可以實(shí)現(xiàn)多個(gè) View

885CF2D9-5211-49EB-9708-E3FE7998B06A.png

但 View 已經(jīng)被統(tǒng)一根據(jù)具體功能放入了所屬的 Contract 里了。

LoginModel 寫起來也很簡單:

93DD27F4-A277-4A33-95BA-E331EE239FC1.png

Model 跟以前的 MVP 的 Model 層比較沒什么差別,主要是考慮到 Model 并不需要抽得太多,Model 也是跟 Presenter 成雙成對(duì)來寫的。

好了,整體思想就是這樣的啦。賣個(gè)萌:


賣萌圖.JPG

有人可能會(huì)想到會(huì)不會(huì)內(nèi)存泄漏,比如我這里使用 RxJava,在哪里取消訂閱呢?內(nèi)存在哪里釋放掉呢?
答案是:不會(huì)發(fā)生內(nèi)存泄漏,內(nèi)存釋放都在 BaseActivity 中處理,因?yàn)?Presenter 數(shù)組存在在 BaseActivity 中的。而且為了統(tǒng)一處理方便,presenter、view、model 都有一個(gè)唯一的基類。
那如何通過 Action 轉(zhuǎn)化成對(duì)應(yīng)的 Presenter、Model、View的?
答案是:通過泛型 + Class<T>,見下圖:

FDA87210-1EF5-4FCF-BF9B-846B9BA92811.png

點(diǎn)擊下載源碼(github)

歡迎各位看官 star 我,同時(shí)有疑問可以隨時(shí)提,我可以隨時(shí)改善。最后,謝謝大家耐心看完!

————2020年3月11日 更新
最近建了微信公眾號(hào)和微博,由我(卷子)和我的好朋友(櫻桃)兩只小程序媛經(jīng)營的。
我們都喜歡程序員這個(gè)呆萌的群體,我們希望能給你帶來技術(shù)上的幫助以及生活上的快樂。嘿嘿~唯一的私心就是 希望你能喜歡我們咯。
大哥,我先敬你一瓶,先干為盡


干了
哎呀呀
我的微信公眾號(hào)
我的微博
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,836評(píng)論 6 540
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,275評(píng)論 3 428
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,904評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,633評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,368評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,736評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,740評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,919評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,481評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,235評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,427評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,968評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,656評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,055評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,348評(píng)論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,160評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,380評(píng)論 2 379

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