原文地址: https://gold.xitu.io/post/58b25e588d6d810057ed3659html
自從Google
在去年放出MVP的官方Sample後,愈來愈多的人開始加入MVP大軍,MVP可謂在16年大放異彩,我也乘勢推出了個人MVP框架狂刷了一波存在感android
但在使用當中我也發現了諸多弊端,致使不少初學者,在寫過Sample後,就再也沒在本身的項目中使用過MVPgit
MVP須要建立太多的類和接口,而且每次通訊都須要繁瑣的經過接口傳遞信息github
這是大多數使用過MVP的朋友,最能感覺到的,最近在幫公司技術面,我也時常問應聘者,可否嘗試着解決這些問題?bash
其實我以前已經有一套解決方案,其實也不能叫解決,只能說是緩解😅架構
所謂硬解決,即是使用比較暴力的方式😂,經過Template自動生成須要的類和接口,這樣少去了頻繁的複製粘貼框架
所謂軟解決,那就要動動腦子,稍微優雅的解決了😀oop
對於邏輯簡單的頁面能夠不使用Presenter,直接在Activity或Fragment中處理邏輯,在Presenter中若是不須要處理數據,也能夠不實用Modelpost
Presenter和Model均可以無限制的重用,因此MVP的劃分不須要太細粒度,稍微粗粒度一點,即不須要每一個Activity或Fragment都給他劃分一套MVP,能夠幾個Activity或Fragment使用同一個Presenter(使用同一個類不是同一個對象,這個Presenter含有能夠共用的邏輯),也可一個Activity或Fragment根據不一樣的需求持有多個不一樣類型的Presenter對象,Model層同理,這樣靈活使用,能夠在必定程度上緩解MVP類和接口較多的缺點學習
經過上面的解決方案,是能夠必定的緩解MVP的缺點,可是並不能徹底解決上述缺點
好比想重用Presenter,Presenter就必須只含有公用的邏輯,而實際項目中公用的邏輯並非那麼多,因此能減小的類和接口也是頗有限的,若是強制將不一樣頁面的邏輯放在同一個Prsenter中,來達到重用的目的,那麼每一個Activity會被迫實現許多並不須要的方法,得不償失
所以我看了大多數MVP框架,尋求如何完全改善這個問題,像支付寶團隊使用的T-MVP框架,是經過將Activity或Fragment做爲Presenter,將UI操做抽到Delegate中,做爲View層
這樣作的好處是,不只能夠少寫不少類,並且Presenter直接就能夠和Activity或Fragment的生命週期作綁定(但使用 Google 最新發布的 Android 架構組件當中的 Lifecycles 就已經能夠很是簡單的讓任何一個類與 Activity 或 Fragment 的生命週期作綁定, 包括 Presenter, 而且 Support Library v26.1.0 已經內嵌這個組件, 不用額外的引入這個組件),且能夠隨便重用View(但大多數場景都是重用Presenter,由於View層變化老是比其它層頻繁)
缺點就是不能重用Presenter,而且對於Presenter的實現有限制,必須是Activity或Fragment,若是要在其餘地方實現Presenter,如Adapter,Dialog就必須根據它的特性從新寫對應的Presenter基類
由於Presenter基類繼承了Activity或Fragment,若是咱們須要經過繼承使用其餘Activity或Fragment,那就又須要修改Presenter基類,一旦某個Activity須要繼承其餘不一樣的Activity,那又須要從新建立一個基於此Activity的Presenter基類,致使一個Activity或Fragment有多個不一樣的Presenter基類
總結一下MVP的缺點
1.粒度很差控制,控制很差就須要寫過多的類和接口
2.如要重用presenter可能會實現過多不須要的接口
3.Presenter和View經過接口通訊太繁瑣,一旦View層須要的數據變化,那麼對應的接口就須要更改
複製代碼
想要在根本上解決以上問題,我想必須換個思路,能不能經過改變傳統MVP架構來解決這些問題?
實現MVP現階段有兩種方式,各有優缺點:
一個是將Activity或Fragment做爲Presenter,抽象一個View層出來
一個是將Activity或Fragment做爲View,抽象一個Presenter層出來
我想達到重用Presenter的目的,天然選擇了後者
在某一天我忽然想到了Handler,他只經過一個handleMessage方法,根據Message的what字段處理不一樣的操做,這樣向上層提供一個統一的入口,下層無論如何改變並不會影響上層,而且一樣能夠實現多種的操做
因而根據這個思想,我從新改造了MVP架構,讓Presenter經過Message和View層通訊
先上張圖
具體作法是,VIEW層持有Presenter對象,當用戶請求一個事件,則調用Presenter中的方法,並把持有View引用Message傳給此方法,此方法處理完請求邏輯後將數據封裝到Message中,並經過Message持有的View引用回調View的handleMessage方法,讓View作不一樣的操做,最後釋放掉Message的全部引用,放入消息池
Presenter並不直接持有View,方法執行完即表示和View的關係解除
和Handler的原理很像,Handler是將消息放入MessageQueue,Looper去輪循處理消息,我這裏是將消息放入,Presenter的方法,並當即處理消息
這樣就能解決上述的缺點:
少寫了不少類和接口
而且Presenter只須要經過handleMessage一個方法與View通訊,也就不用繁瑣的一直添加接口方法,只須要一個Message參數,經過Message封裝數據,即便View須要的數據類型發生改變,也不須要更改任何方法,因此也不會影響上層調用
隨便重用Presenter,即便你一個Activity,重用10個不一樣的Presenter,那也只用實現一個handleMessage方法,不須要實現View中其餘用不到的方法,經過一個方法一樣能作到不一樣的操做(傳統MVP一個頁面對應一個Presenter,其實大多數Presenter只有一兩個方法,這樣致使存在大量代碼寥寥無幾的Presenter,你有想過將相近的邏輯都寫到一個Presenter中,一直重用Presenter有多爽嗎😁)
當Presenter中的方法須要Activity傳遞一些數據時,也能夠將數據封裝到Message中傳給Presenter,這樣即便須要的數據類型發生改變,也不須要更改方法,因此也不會影響上層調用
只有能不斷的靈活重用,才能感覺到MVP的強大之處
固然不少不一樣的邏輯都寫在一個Presenter中,雖然能夠少寫不少類,可是後面的擴展性確定很差,因此這個粒度須要本身控制,可是對於外包項目簡直是福音
說了這麼多仍是要看看Demo,具體該怎麼作吧?
掃碼關注個人公衆號 JessYan,一塊兒學習進步,若是框架有更新,我也會在公衆號上第一時間通知你們
Hello 我叫 JessYan,若是您喜歡個人文章,能夠在如下平臺關注我
-- The end