傳統(tǒng)MVP用在項(xiàng)目中是真的方便還是累贅?

原文地址: http://www.itdecent.cn/p/ac51c9b88af3
qq群:301733278

前言(最后奉上福利)

自從Google在去年放出MVP官方Sample后,越來越多的人開始加入MVP大軍,MVP可謂在16年大放異彩,我也乘勢(shì)推出了我的MVP框架狂刷了一波存在感

問題

但在使用當(dāng)中我也發(fā)現(xiàn)了諸多弊端,導(dǎo)致很多初學(xué)者,在寫過Sample后,就再也沒在自己的項(xiàng)目中使用過MVP

MVP需要?jiǎng)?chuàng)建太多的類和接口,并且每次通信都需要繁瑣的通過接口傳遞信息

這是大多數(shù)使用過MVP的朋友,最能感受到的,最近在幫公司技術(shù)面,我也時(shí)常問應(yīng)聘者,能否嘗試著解決這些問題?

解決方案

其實(shí)我之前已經(jīng)有一套解決方案,其實(shí)也不能叫解決,只能說是緩解

硬解決

所謂硬解決,便是使用比較暴力的方式,通過Template自動(dòng)生成需要的類和接口,這樣少去了頻繁的復(fù)制粘貼

軟解決

所謂軟解決,那就要?jiǎng)觿?dòng)腦子,稍微優(yōu)雅的解決了

  1. 對(duì)于邏輯簡(jiǎn)單的頁面可以不使用Presenter,直接在ActivityFragment中處理邏輯,在Presenter中如果不需要處理數(shù)據(jù),也可以不使用Model

  2. PresenterModel都可以無限制的重用,所以MVP的劃分不需要太細(xì)粒度,稍微粗粒度一點(diǎn),即不需要每個(gè)ActivityFragment都給他劃分一套MVP,可以幾個(gè)ActivityFragment使用同一個(gè)Presenter(使用同一個(gè)類不是同一個(gè)對(duì)象,這個(gè)Presenter含有可以共用的邏輯),也可一個(gè)ActivityFragment根據(jù)不同的需求持有多個(gè)不同類型的Presenter對(duì)象,Model層同理,這樣靈活使用,可以在一定程度上緩解MVP類和接口較多的缺點(diǎn)

并沒有完全解決問題

通過上面的解決方案,是可以一定的緩解MVP的缺點(diǎn),但是并不能完全解決上述缺點(diǎn)

比如想重用Presenter,Presenter就必須只含有公用的邏輯,而實(shí)際項(xiàng)目中公用的邏輯并不是那么多,所以能減少的類和接口也是很有限的,如果強(qiáng)制將不同頁面的邏輯放在同一個(gè)Prsenter中,來達(dá)到重用的目的,那么每個(gè)Activity會(huì)被迫實(shí)現(xiàn)許多并不需要的方法,得不償失

尋求解決方法

因此我看了大多數(shù)MVP框架,尋求如何徹底改善這個(gè)問題,像支付寶團(tuán)隊(duì)使用的TheMVP框架,是通過將ActivityFragment作為Presenter,將UI操作抽到Delegate中,作為View

TheMVP優(yōu)點(diǎn)

這樣做的好處是,不僅可以少寫很多類,而且Presenter直接就可以和ActivityFragment的生命周期做綁定 (但使用 Google 最新發(fā)布的 Android 架構(gòu)組件當(dāng)中的 Lifecycles 就已經(jīng)可以非常簡(jiǎn)單的讓任何一個(gè)類與 ActivityFragment 的生命周期做綁定, 包括 Presenter, 并且 Support Library v26.1.0 已經(jīng)內(nèi)嵌這個(gè)組件, 不用額外的引入這個(gè)組件), 且可以隨便重用View(但大多數(shù)場(chǎng)景都是重用Presenter,因?yàn)?strong>View層變化總是比其它層頻繁)

TheMVP缺點(diǎn)

缺點(diǎn)就是不能重用Presenter,并且對(duì)于Presenter的實(shí)現(xiàn)有限制,必須是ActivityFragment,如果要在其他地方實(shí)現(xiàn)Presenter,如Adapter,Dialog就必須根據(jù)它的特性重新寫對(duì)應(yīng)的Presenter基類

因?yàn)?strong>Presenter基類繼承了ActivityFragment,如果我們需要通過繼承使用其他ActivityFragment,那就又需要修改Presenter基類,一旦某個(gè)Activity需要繼承其他不同的Activity,那又需要重新創(chuàng)建一個(gè)基于此ActivityPresenter基類,導(dǎo)致一個(gè)ActivityFragment有多個(gè)不同的Presenter基類

分析問題,解決問題

總結(jié)一下MVP的缺點(diǎn)

1.粒度不好控制,控制不好就需要寫過多的類和接口
2.如要重用presenter可能會(huì)實(shí)現(xiàn)過多不需要的接口
3.Presenter和View通過接口通信太繁瑣,一旦View層需要的數(shù)據(jù)變化,那么對(duì)應(yīng)的接口就需要更改

想要在根本上解決以上問題,我想必須換個(gè)思路,能不能通過改變傳統(tǒng)MVP架構(gòu)來解決這些問題?

實(shí)現(xiàn)MVP現(xiàn)階段有兩種方式,各有優(yōu)缺點(diǎn):

一個(gè)是將ActivityFragment作為Presenter,抽象一個(gè)View層出來

一個(gè)是將ActivityFragment作為View,抽象一個(gè)Presenter層出來

我想達(dá)到重用Presenter的目的,自然選擇了后者

在某一天我突然想到了Handler,他只通過一個(gè)handleMessage方法,根據(jù)Messagewhat字段處理不同的操作,這樣向上層提供一個(gè)統(tǒng)一的入口,下層不管如何改變并不會(huì)影響上層,并且同樣可以實(shí)現(xiàn)多種的操作

于是根據(jù)這個(gè)思想,我重新改造了MVP架構(gòu),讓Presenter通過MessageView層通信

如何實(shí)現(xiàn)

先上張圖

Architecture.png

具體做法是,VIEW層持有Presenter對(duì)象,當(dāng)用戶請(qǐng)求一個(gè)事件,則調(diào)用Presenter中的方法,并把持有View引用Message傳給此方法,此方法處理完請(qǐng)求邏輯后將數(shù)據(jù)封裝到Message中,并通過Message持有的View引用回調(diào)ViewhandleMessage方法,讓View做不同的操作,最后釋放掉Message的所有引用,放入消息池

Presenter并不直接持有View,方法執(zhí)行完即表示和View的關(guān)系解除

Handler的原理很像,Handler是將消息放入MessageQueue,Looper去輪循處理消息,我這里是將消息放入,Presenter的方法,并立即處理消息

總結(jié)

這樣就能解決上述的缺點(diǎn):

  1. 少寫了很多類和接口

  2. 并且Presenter只需要通過handleMessage一個(gè)方法與View通信,也就不用繁瑣的一直添加接口方法,只需要一個(gè)Message參數(shù),通過Message封裝數(shù)據(jù),即使View需要的數(shù)據(jù)類型發(fā)生改變,也不需要更改任何方法,所以也不會(huì)影響上層調(diào)用

  3. 隨便重用Presenter,即使你一個(gè)Activity,重用10個(gè)不同的Presenter,那也只用實(shí)現(xiàn)一個(gè)handleMessage方法,不需要實(shí)現(xiàn)View中其他用不到的方法,通過一個(gè)方法同樣能做到不同的操作(傳統(tǒng)MVP一個(gè)頁面對(duì)應(yīng)一個(gè)Presenter,其實(shí)大多數(shù)Presenter只有一兩個(gè)方法,這樣導(dǎo)致存在大量代碼寥寥無幾的Presenter,你有想過將相近的邏輯都寫到一個(gè)Presenter中,一直重用Presenter有多爽嗎)

  4. 當(dāng)Presenter中的方法需要Activity傳遞一些數(shù)據(jù)時(shí),也可以將數(shù)據(jù)封裝到Message中傳給Presenter,這樣即使需要的數(shù)據(jù)類型發(fā)生改變,也不需要更改方法,所以也不會(huì)影響上層調(diào)用

只有能不斷的靈活重用,才能感受到MVP的強(qiáng)大之處

當(dāng)然很多不同的邏輯都寫在一個(gè)Presenter中,雖然可以少寫很多類,但是后面的擴(kuò)展性肯定不好,所以這個(gè)粒度需要自己控制,但是對(duì)于外包項(xiàng)目簡(jiǎn)直是福音

說了這么多還是要看看Demo,具體該怎么做吧?

Go!覺得好一定要右上角Star哦!

公眾號(hào)

掃碼關(guān)注我的公眾號(hào) JessYan,一起學(xué)習(xí)進(jìn)步,如果框架有更新,我也會(huì)在公眾號(hào)上第一時(shí)間通知大家

公眾號(hào)

Hello 我叫 JessYan,如果您喜歡我的文章,可以在以下平臺(tái)關(guān)注我

-- The end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容