APP架子遷移指南(三)

在完成上一篇以後,斷斷續續的開始重構個人Android項目代碼,如今終於完成了。在重構期間又仔細閱讀了一些開源項目的源碼及文章,並詢問了一些大神思路,按照理解本身完成了MVP結構的重構,與google samples項目的大體一致,但沒有徹底照搬。本文側重一些重構過程當中思考的問題,,具體的代碼能夠在Github查看,本文的源碼爲branch1.1,重構前的是master,最好對比看看重構的區別。git

對多重callback邏輯的思考

大量的文章都只介紹讀取一次網絡而後用一個監聽接口處理訪問狀態,這種是最多見的網絡訪問規則,以下圖所示:github


用監聽的方式獲取訪問結果

但實際生產環境哪裏僅僅是簡單的爲列表獲取數據而已,要是完成業務邏輯須要屢次網絡訪問呢?來看一次登陸過程,我將每個步驟都截圖以下:編程


基於UMENG SDK訪問微信獲取token,成功則執行下一步


1.基於UMENG SDK訪問微信獲取token,成功執行下一步。數組


基於UMENG SDK獲取用戶資料(頭像、暱稱),成功則執行下一步


2.基於UMENG SDK獲取用戶資料(頭像、暱稱),成功則執行下一步。安全


將數據發送服務器進行登陸驗證


3.將數據發送服務器進行登陸驗證,完成登陸業務。服務器

提及來邏輯很簡單,可是從代碼實現角度就不夠優雅了。在OnSuccess中執行下一步動做,若是不寫在另外一個方法函數中的話,那麼看起來就是一層套一層的結構,可讀性不好,我考慮的有幾種技巧來儘可能提升可讀性:微信

1.添加充足的註釋 2.用Handler(以前我是這麼作的) 3.用EventBus 4.用RxJava

在此次重構中,我放棄了Handler的方式,若是註釋充足,Handler其實並無提升可讀性,並且從MVP架構的角度來思考,以前Handler的編寫並無將View邏輯與Presenter的邏輯分離,所有放在了Handler中,應該儘可能避免。網絡


放棄handler了

EventBus在重構中也未使用,由於EventBus的訂閱模式更適合一個操做須要通知多個處理的狀況(好比收到新消息),不然與監聽接口相比閱讀性。並未提高太大。架構

我傾向使用RxJava,雖然準備在下一次重構中才使用,但已經閱讀了很多的文章。在註釋充足的狀況下,如今callback套callback的方式已經可以閱讀,但不可忽略的線程安全和內存溢出問題,能夠利用RxJava很好的解決(這也是放棄handler的一個緣由,你真覺得實際生產中new一個出來就能夠無論了麼..)感興趣的朋友能夠等個人下一個branch,我會來講說個人感覺。框架

MVP重構要一向堅持到底麼?

在google sample的todo例子中,要想從列表頁打開新建頁,須要點擊浮動按鈕,這樣一個簡單的在onClick中搞定的事情,被拆分爲三部分,我認爲實際有點過了。看看下面的代碼:


菜單欄按鈕點擊事件

若是點擊消息列表的按鈕,須要首先清除通知badage,而後清除Preference的未讀數量,而後進行頁面跳轉。按照MVP架構思路,清除通知badage應該在View中實現(也就是在Activity裏多一個方法);清除未讀數量應該在Model的Local中(也就是專門負責本地數據操做的類);跳轉應該在View中實現(Activity裏面還要多寫一個方法)。

那麼其實在OnClick中3行代碼搞定的時候,你要額外多謝那麼多支撐框架的代碼,有必要麼?再看看Model層的一個例子:

在google sample的todo例子中,網絡訪問與本地訪問分離,一條數據是從本地讀取仍是從網絡讀取的邏輯判斷,是寫在Repository中的。如此毫無問題,思路很是清晰。但若是不存在本地化的須要,能夠把代碼直接寫在Repository中麼?(其實能夠吧...反正也不影響閱讀)


重構以後層次很乾淨

todo例子中,網絡與本地的操做是保持一致的(基礎的增刪改查),用接口來定義了方法。在實際生產中(好比登陸過程),本地與網絡的操做差異比較大,所以應該根據實際判斷究竟是否須要用接口定義方法。

todo例子中,用到了不少Ioc的思想,若是你不用DI庫如dagger2或者要作單元測試,能夠考慮簡化一下,正如我實例化Presenter的代碼同樣。

重構以後,數據的成員變量該放哪去了?

詳情頁,須要一個描述商品數據的成員變量;其餘用戶的介紹頁,須要一個描述用戶資料數據的成員變量;列表,須要一個數組來保存數據,一個int來保存如今是第幾頁了。那麼MVP結構重構以後,這些變量是不該該仍然定義在Activity中的,那麼這些數據應該放在MVP的那一層呢?

安裝todo例子中的介紹,包含2方面的重構。首先,數據變量應該寫在P層中;其次,對ListView這種包含adapter的控件,數組操做應該寫到Adapter中。


Presenter的構造器

以我一個Presenter爲例,因爲不考慮注入,所以Repository就直接在構造器中本身實例化了。當前列表爲第幾頁的mPage變量,是放在Presenter中了的,每次獲取數據後都直接將數據傳入View中,再在View中調用Adapter的自定義方法來更新列表(詳情見代碼)。


ListView的數據操做都在Adapter中定義

在Adapter中,自定義了remove、replace、addAll、getItem等幾種經常使用的數據操做函數,不夠再加就是了。自定義這些方法的時候,尤爲要注意你是否本身實現了header-view的功能,若是實現了,那麼就要計算一下實際的位置(其實特簡單,一句話的事)。

後話

其實原本想按照重構後MVP長什麼樣的思路來寫這文章,可是在重構的過程當中不斷的閱讀todo例子的代碼,以爲把握住幾個關鍵點,重構的思路就會很是清晰:

1.各類數據操做都要放到M層中去; 2.V層中只須要定義方法的時候把數據設爲參數,無論數據從哪來,到哪去; 3.P層負責告訴M層要讀哪些數據(get)或者要向服務器發送什麼數據(set),根據數據訪問狀況(成功或失敗),將數據傳給V層;

這一篇更多的是想把本身重構過程當中的一些思考記下來和你們一塊兒討論,本篇不是此次重構的終點,下一篇我會繼續聊如何從這一步繼續跨到RxJava函數式編程的範圍去。每一次重構是怎麼變化的,代碼也給了,思路也給了,項目也是應用商店上線的產品(雖然沒有錢推廣用的人很少),這個系列應該比其餘文章的玩具代碼參考價值更高吧。若有感興趣的大神指點一二,或者也在前行的朋友一塊兒來討論下,那我也以爲深夜碼字沒有白費了。

相關文章
相關標籤/搜索