上次對mvp的表面概念作出了一些思考【對於mvp、響應式程式設計以及事件匯流排的一些思考】。而隨著對自己的mvp框架深入優化、擴充套件,也發現了一些疑惑的地方。相信接觸過mvp框架的都清楚,針對
model-view-presenter
這三者,都會為其單獨建立乙個inte***ce,規範其各自的行為。舉個例子,乙個登入用的activity,在這裡將其命名為loginactivity
,其對應的presenter和model為loginpresenter
和loginmodel
,而其各自的介面則為iloginview
、iloginpresenter
、iloginmodel
。
看,乙個登入頁面,就產生了3個介面檔案。而隨著應用複雜度提高,介面檔案的數量將隨之劇增——我將其稱為「介面膨脹」。
因此,後來有人通過建立contract
類來規範介面,比如:
public
inte***ce
logincontract
public
inte***ce
iloginpresenter
public
inte***ce
iloginmodel
}
這樣,乙個頁面對應乙個contract
,減少了介面的生成數量。我覺得相對之前的情況,contract
的引入使得mvp專案相對簡潔不少。
但是,我們是否真的需要這麼多介面?
對此,我覺得應該再次審視mvp的本質——就是解耦。而介面是最充分發揮解耦功能的方式。而如何和應用的實際情況相結合,這是乙個動態平衡的問題。也許有的專案針對model層的改動很大,呼叫的地方很多,這時候model完全拋棄介面不一定是件好事;而有的專案p層的使用極為有限,建立過多的inte***ce確實是浪費時間和增加method數。
所以對我而言,我的取捨是:model去掉介面,但是每個v針對乙個m,即確保v:p:m是1:1:1的關係。這樣即使要改動乙個m,也僅是改動乙個p即可。雖然這樣也是有缺點:當m層內所呼叫的多個操作有所變動,可能需要改動特別多的地方,但這保證了只影響m層,其他層不受影響。
而p層的inte***ce,我還是選擇保留,與view共同寫在contract中——除非對method數有要求。
其實這是乙個很小的點。比如說,有的人喜歡分類將所有activity放到同乙個包中,按型別建包;有的喜歡按照需求功能,比如login部分都放到同乙個包,按功能建包。
按照google的demo,結合contract,demo選的是按功能建包,同一功能的都放到同乙個包中。
但是會有這樣一種情況——假設我現在寫乙個應用內的文章模組,它包含有:
列表頁詳情頁
投稿頁etc.
這樣,如果按照上述分包策略,這部分的所有m、v、p都放進乙個article
的包內,是否又顯得過於臃腫?
又或者,再按照功能點細分,就會有如下分包
這樣,保證了每個包內僅有一組 m、v、p和contract,結構上是非常清晰。不過,我們是否真的需要如此多的包呢?
其實只要不是按照上述第一種方法分包,恐怕任何方式的分包都會導致包的數量增加。我看到有的專案會將contract抽離出單獨乙個包,所有contract都寫在裡面;而m、v、p都各自乙個包,雖然這樣也夠直觀,但是各自內部不會再分包,這樣又是否夠清晰呢?
事實上,分包也只是個人喜好,到底如何分,隨君喜好吧!
有一種情況:當應用回到後台,再次回到前台時,可能v層已經被記憶體**,這時候如何讓p層與v層重新建立聯絡,並且盡可能恢復資料?
p層與v層共存亡
資料不應儲存在p層
是的,乙個應用所產生的臨時資料不應該記錄在p層,但一些臨時變數可以。比如乙個列表頁的資料,從伺服器獲取下來後,應該在m層保持住;而使用者滑動到列表頁的第幾層,則可以記錄在p層。
那麼,如何恢復資料呢?
首先明確乙個觀點,即上述第一點,p與v共存亡,既然v被**了,p也不會存在,所以v重新被建立了,p也隨著v的建立而建立。
所以第一種方法,就是最常用的,將資料儲存到v的bundle中,隨著v被重新建立,取出bundle的資料給回p層,再從p層回到m層。
但是上述文章有提到一點,即把資料保持在m層。
m層其實並不是必須跟隨v的生命週期,畢竟它不關心p、v,它只負責運算元據。所以m層可以通過靜態變數等手段保持資料到記憶體,當p、v重新建立時,再從m處取得資料。
實際上這種方式更符合mvp的思想,甚至由此可以輔助處理不常變動的網路資料,將資料快取到記憶體中,無需多次請求網路,畢竟相比之下請求網路的操作和記憶體相比代價還是略高。
在這裡,我只給出這種思考點,至於如何使用,或者有更好的方式,都要看實際需求決定。
依然舉乙個例子:當乙個activity內用viewpager之類的包裹4個fragment,如何合理地處理其邏輯和資料互動?
起初我的想法是,fragment也只是乙個控制項view,因此我認為」fragment和activity共用乙個presenter和model「,這樣就能減少管理複雜度,也無需考慮資料的傳遞——畢竟資料都在同乙個presenter和model裡打轉。
後來我意識到這個想法是錯誤的,一是這樣違背了使用mvp的初衷,二是fragment也有其自身的生命週期,以及它自身的特性注定了它可以承擔複雜的頁面邏輯,這些在mvp架構下離不開p的加持。
建立fragment時通過setargument()設定引數:activity ---> fragment(create)
activity和fragment之間互相互動:activity <===> fragment
fragment之間互相互動:fragment <===> fragment
排除第一種流向,最麻煩的就是在第2、3種情況下,彼此互動的資料型別十分多(比如activity和fragment、fragment之間的資料互動型別例項分別有5~10種),怎麼辦呢?
我認為的解決方法是,在不使用bus類的方法上,針對每種資料型別,都建立對應的repository,在需要互動的v層所對應的model上呼叫其對應的repository,並根據repository提供訂閱的observable,供p層呼叫,畢竟決定互動資料的邏輯是由p決定的;然後,當其中乙個v產生資料,將通過p層傳遞到m層,m層內部將資料傳送到repository,而訂閱了該repository的p層將收到資料從而處理v層。
是的,上述的方法稍微有點傻,但是考慮到解耦和日後修改時的難易度,個人感覺可以接受。
什麼?你說如果資料型別在10種、20種、甚至上百種呢?
那就重構吧!
架構往往是提供一種思考正規化,而不是硬性規定,任何架構或者思想總有無法涉及或者無法處理的問題,這時候就考驗到使用者如何靈活地變通運用。mvp是個很好的框架,但基於android自身的設計,始終無法做到徹底地將各層次分離開來;而引入響應式程式設計,我覺得是乙個很好的靈活處理方式,雖然mvp不是必須依賴響應式,但是通過事件響應、資料響應,可以更好地處理mvp裡同層級間的聯絡(如m與m間的資料流動),這一點是很多文章沒有提及到的。
這些思考僅一己之見,還需實戰實驗,還望能拋磚引玉!
對於工作的一些思考
感覺自從領導讓我管專案以來,一直沒有讓領導很滿意的地方是自己在專案上花的心思太少.很簡單的一些例子就證明了,比如自己雖然是中途接手的專案,然後並沒有仔細檢視招標檔案,沒有針對招標檔案的要求 去核對乙方的一些功能是否完成.其次,對於乙方,我還在心裡上和行動上 做到完成把控住,我不僅要去分析我領導的想法...
對於切片的一些理解
使用技巧 type struct 乙個切片是由資料指標加上長度和容量組成的,類似與c 中的vector。var a int 等價於nil b int 表示乙個空的切片,不等於nil c int len,cap都為3的切片 d c 2 cap為3,len為2。與c共享一片記憶體位址 e c 0 2 c...
對於爬蟲的一些思考
由於專案並不會投入太多的時間,所以穩定性能是最終的。穩定性的可以從以下的維度進行考慮 資料量不多的時候採用單執行緒。異常處理。重試。詳細的日誌。個人覺得資料量少就是在40小時內遍歷全部並且可以爬完的就是小資料量。異常處理主要就是放在請求 時 入庫。而重試主要是用traceback這個庫,它的作用是捕...