傳統MVP用在項目中是真的方便仍是累贅?

原文地址: https://gold.xitu.io/post/58b25e588d6d810057ed3659html

前言(最後奉上福利)

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

問題

但在使用當中我也發現了諸多弊端,致使不少初學者,在寫過Sample後,就再也沒在本身的項目中使用過MVPgit

MVP須要建立太多的類和接口,而且每次通訊都須要繁瑣的經過接口傳遞信息github

這是大多數使用過MVP的朋友,最能感覺到的,最近在幫公司技術面,我也時常問應聘者,可否嘗試着解決這些問題?bash

解決方案

其實我以前已經有一套解決方案,其實也不能叫解決,只能說是緩解😅架構

硬解決

所謂硬解決,即是使用比較暴力的方式😂,經過Template自動生成須要的類和接口,這樣少去了頻繁的複製粘貼框架

軟解決

所謂軟解決,那就要動動腦子,稍微優雅的解決了😀oop

  1. 對於邏輯簡單的頁面能夠不使用Presenter,直接在ActivityFragment中處理邏輯,在Presenter中若是不須要處理數據,也能夠不實用Modelpost

  2. PresenterModel均可以無限制的重用,因此MVP的劃分不須要太細粒度,稍微粗粒度一點,即不須要每一個ActivityFragment都給他劃分一套MVP,能夠幾個ActivityFragment使用同一個Presenter(使用同一個類不是同一個對象,這個Presenter含有能夠共用的邏輯),也可一個ActivityFragment根據不一樣的需求持有多個不一樣類型的Presenter對象,Model層同理,這樣靈活使用,能夠在必定程度上緩解MVP類和接口較多的缺點學習

並無徹底解決問題

經過上面的解決方案,是能夠必定的緩解MVP的缺點,可是並不能徹底解決上述缺點

好比想重用Presenter,Presenter就必須只含有公用的邏輯,而實際項目中公用的邏輯並非那麼多,因此能減小的類和接口也是頗有限的,若是強制將不一樣頁面的邏輯放在同一個Prsenter中,來達到重用的目的,那麼每一個Activity會被迫實現許多並不須要的方法,得不償失

尋求解決方法

所以我看了大多數MVP框架,尋求如何完全改善這個問題,像支付寶團隊使用的T-MVP框架,是經過將ActivityFragment做爲Presenter,將UI操做抽到Delegate中,做爲View

TheMVP優勢

這樣作的好處是,不只能夠少寫不少類,並且Presenter直接就能夠和ActivityFragment的生命週期作綁定(但使用 Google 最新發布的 Android 架構組件當中的 Lifecycles 就已經能夠很是簡單的讓任何一個類與 ActivityFragment 的生命週期作綁定, 包括 Presenter, 而且 Support Library v26.1.0 已經內嵌這個組件, 不用額外的引入這個組件),且能夠隨便重用View(但大多數場景都是重用Presenter,由於View層變化老是比其它層頻繁)

TheMVP缺點

缺點就是不能重用Presenter,而且對於Presenter的實現有限制,必須是ActivityFragment,若是要在其餘地方實現Presenter,如Adapter,Dialog就必須根據它的特性從新寫對應的Presenter基類

由於Presenter基類繼承了ActivityFragment,若是咱們須要經過繼承使用其餘ActivityFragment,那就又須要修改Presenter基類,一旦某個Activity須要繼承其餘不一樣的Activity,那又須要從新建立一個基於此ActivityPresenter基類,致使一個ActivityFragment有多個不一樣的Presenter基類

分析問題,解決問題

總結一下MVP的缺點

1.粒度很差控制,控制很差就須要寫過多的類和接口
2.如要重用presenter可能會實現過多不須要的接口
3.Presenter和View經過接口通訊太繁瑣,一旦View層須要的數據變化,那麼對應的接口就須要更改

複製代碼

想要在根本上解決以上問題,我想必須換個思路,能不能經過改變傳統MVP架構來解決這些問題?

實現MVP現階段有兩種方式,各有優缺點:

一個是將ActivityFragment做爲Presenter,抽象一個View層出來

一個是將ActivityFragment做爲View,抽象一個Presenter層出來

我想達到重用Presenter的目的,天然選擇了後者

在某一天我忽然想到了Handler,他只經過一個handleMessage方法,根據Messagewhat字段處理不一樣的操做,這樣向上層提供一個統一的入口,下層無論如何改變並不會影響上層,而且一樣能夠實現多種的操做

因而根據這個思想,我從新改造了MVP架構,讓Presenter經過MessageView層通訊

如何實現

先上張圖

具體作法是,VIEW層持有Presenter對象,當用戶請求一個事件,則調用Presenter中的方法,並把持有View引用Message傳給此方法,此方法處理完請求邏輯後將數據封裝到Message中,並經過Message持有的View引用回調ViewhandleMessage方法,讓View作不一樣的操做,最後釋放掉Message的全部引用,放入消息池

Presenter並不直接持有View,方法執行完即表示和View的關係解除

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

總結

這樣就能解決上述的缺點:

  1. 少寫了不少類和接口

  2. 而且Presenter只須要經過handleMessage一個方法與View通訊,也就不用繁瑣的一直添加接口方法,只須要一個Message參數,經過Message封裝數據,即便View須要的數據類型發生改變,也不須要更改任何方法,因此也不會影響上層調用

  3. 隨便重用Presenter,即便你一個Activity,重用10個不一樣的Presenter,那也只用實現一個handleMessage方法,不須要實現View中其餘用不到的方法,經過一個方法一樣能作到不一樣的操做(傳統MVP一個頁面對應一個Presenter,其實大多數Presenter只有一兩個方法,這樣致使存在大量代碼寥寥無幾的Presenter,你有想過將相近的邏輯都寫到一個Presenter中,一直重用Presenter有多爽嗎😁)

  4. Presenter中的方法須要Activity傳遞一些數據時,也能夠將數據封裝到Message中傳給Presenter,這樣即便須要的數據類型發生改變,也不須要更改方法,因此也不會影響上層調用

只有能不斷的靈活重用,才能感覺到MVP的強大之處

固然不少不一樣的邏輯都寫在一個Presenter中,雖然能夠少寫不少類,可是後面的擴展性確定很差,因此這個粒度須要本身控制,可是對於外包項目簡直是福音

說了這麼多仍是要看看Demo,具體該怎麼作吧?

Go!以爲好必定要右上角Star哦!

公衆號

掃碼關注個人公衆號 JessYan,一塊兒學習進步,若是框架有更新,我也會在公衆號上第一時間通知你們


Hello 我叫 JessYan,若是您喜歡個人文章,能夠在如下平臺關注我

-- The end

相關文章
相關標籤/搜索