歡迎光臨
每天分享高質量文章

Kotlin + Mvp + RxJava + Retrofit 心得體會

作者:Walkud

鏈接:https://www.jianshu.com/p/4cb1a56acf9e

 

先上本專案 Github 地址:
https://github.com/Walkud/JudyKotlinMvp

首先宣告

本專案是參考 git-xuhao/KotlinMvp ,對原專案 Mvp 核心代碼及 Adapter 代碼按照自己的想法進行了重構,佈局 (xml) 檔案(除 fragment_mine.xml )、工具類、自定義 View 都直接使用的原專案的檔案,本專案的主要目的是為了 Kotlin 學習,將自己對 Java 版 Mvp 的理解用 Kotlin 實現。

說明

我希望用盡可能少的文字和代碼來說明是自己對 Mvp 的理解。

Mvp

Mvp 最主要的目的就是為瞭解耦,讓各個模塊各司其職。

M (Model)


負責業務模型的構建,可簡單理解為P所需要的資料結構就在這一層處理及封裝(包括網絡、Sqlite、sp等)。

可參考 MainModel ,Model的粒度根據實際情況自行控制。

P (Presenter)

負責處理業務邏輯,可簡單理解為業務中的UI操作、 if 判斷等。

UI操作不僅僅是呼叫 UI 的資料更新操作,還包含何時顯示進度框、隱藏進度框、系結Ui生命周期等。

model.getSearchResult(keyWords!!)
        .compose(NetTransformer())//異步調度(異步發起請求 --> 主執行緒回呼)
        .compose(ProgressTransformer(view))//進度框的顯示與隱藏
        .compose(bindUntilOnDestroyEvent())//系結UI生命周期 (PS: 生命周期時機可控)
        .subscribe(object : RxSubscribe() {
            ……
        })

以上代碼用三行代碼進行了異步調度、進度框顯示與隱藏控制、UI 的宣告周期系結(防止記憶體泄漏)操作,這就是 RxJava 魅力所在。

可參考 VideoDetailPresenter

V (View)


負責提供 UI 交互的能力,可簡單理解為 V 監聽到用戶的點擊事件 –> P 處理業務邏輯 –> V 更新UI。

Activity、Fragment 為 V ,其中 Adapter、View(xml、自定義View)、Dialog 等為 V 的一部分,所有的交互事件都放在 Activity 和 Fragment 中進行監聽,便於日後定位。

專案中 Mvp 實現

//依賴關係
View   Presenter —— > Model

本專案中使用泛型來指定依賴關係,且直接依賴的具體實現,並沒有依賴抽象,可以有效提高開發效率,但違背了設計原則,個人認為過於看重這些原則,導致開發效率降低也有些得不償失。

//基類 V  (MvpFragment 同理)
abstract class MvpActivity<P> : MvcActivity() {
    val presenter: P by lazy {
        getP()
    }
    /**
     * 獲取邏輯處理實體,子類實現
     */
    abstract fun getP(): P
    …… 
}

//具體實現
class SearchActivity : MvpActivity() {//泛型指定 P 的依賴關係
    // 這裡實體化 P 並且 註入 V
    override fun getP() = SearchPresenter().apply { view = this@SearchActivity }
}

//基類 P
open class BasePresenter<V : Anyout M> : ViewLifecycle() {
    /**
     * UI視圖,即Activity或Fragment
     */
    var view: V by Delegates.notNull()

    /**
     * 業務模型,即XXXModel,這裡使用java反射(kotlin反射太慢,暫時不建議使用)創建示例,省去在每個Presenter中創建實體
     */
    val model: M by lazy {
      //這裡使用 Java 反射實體化 M,
      ReflectionUtils.getSuperClassGenricType(this1)
    }
    ……
}

//具體實現
class SearchPresenter : BasePresenter<SearchActivityMainModel>() {//泛型指定 V 和 M 的具體實現
    ……
}

通過上面代碼,Mvp 之間的關係就建立起來了,需要註意的是 M 是通過Java 反射實體化的(省去在 P 的實現類中去實體化,直接使用即可),具體使用請參考代碼。

MvpActivity
BasePresenter

解決痛點

抽象(創建過多無用的接口)

之前用過 Mvp 的在這點上應該深有體會,直接依賴具體實現可以很好的解決這個問題,對於需要復用的地方也可以指定泛型為接口,從而達到可復用目的,實際專案中這種復用需求很少。

異步導致的記憶體泄漏

異步時間過長而界面已退出,回呼中依然隱式的持有 Activity 實體,這個問題在開發中很常見,所以本專案中使用了 RxJava (異步利器)來處理異步問題,由於它的靈活性,在加上另外一位大神開源庫 RxLifecycle 可以很方便的處理這個問題,而且使代碼也非常美觀(一行代碼搞定),最重要的是處理時機可控(比如在 onStop 或 onDestory )。

//為了控制篇幅,偷懶了,參照前面貼的代碼
compose(bindUntilOnDestroyEvent())//系結UI生命周期 (PS: 生命周期時機可控)

進度UI的控制

對於彈框進度、下拉掃清、上拉加載、異常佈局等控制問題,使用 RxJava 可以完美的解決,一行代碼解放開發者大腦,不需要再去想何時顯示、何時隱藏。

//為了控制篇幅,偷懶了,參照前面貼的代碼
compose(ProgressTransformer(view))//進度框的顯示與隱藏

ProgressTransformer

交互都由 Activity 或 Fragment 來處理

有沒有同學遇到修改遺留 Bug 找某個點擊事件的時候,要跳轉 N 個類,最後發現事件監聽裡面發了一個 Event 事件,然後又得找是誰消費了事件,發現居然有 N 個類都有消費(一臉懵逼,我的真實遭遇。。。) ,本專案的處理方式是將最終的監聽都放在 V 中 的 addListener 方法中,找交互事件的時候可以快速定位。

RxJava

RxJava 使代碼更連貫、邏輯更清晰(特別是去看原來的代碼)、簡潔,專案中使用了 RxJava 優雅的解決了異步調度、進度框顯示與隱藏控制、UI 的宣告周期系結的問題,使用簡單靈活。

RxJava 對於初學者來說,算是一個比較難上手的庫,網上也有很多文章,但看完之後也不知道哪裡好用,哪裡簡潔。在這裡分享一個我最初學習的方法:

  1. 先依葫蘆畫瓢,硬著頭皮去使用,對 RxJava 有個初步的概念。

  2. 有了初步的概念,回頭再去看文章會有不一樣的體會,會理解作者在說什麼,隨便學習幾個常用的運算子。

  3. 結合自己的理解,最好能從生活中找個例子對照理解。

  4. 學習理解更多的運算子及運算子示意圖。

  5. fuck 原始碼、分享、寫文章。

以上方法不適合所有人,以後有機會我也寫寫對 RxJava 的理解。

Retrofit

Retrofit 是一個遵循 RESTful 設計標準的一個網絡請求封裝庫。

Retrofit 使用了大量的設計樣式,其中動態代理 + 註解的思路來宣告後端接口非常優雅,再加上提供網絡請求配接器及資料轉換器的擴展,基本上已滿足大部分的業務需求了。

Retrofit簡易流程圖.jpg

上圖是我整理的一個 Retrofit 簡易流程圖。Retrofit 原始碼推薦閱讀,難度小,裡面的技術知識非常多,可以在網上找篇原始碼分的文章結合著看。

總結

  • 分享自己對 Mvp 的理解。

  • 分享瞭如何優雅的解決異步調度、進度框顯示與隱藏控制、UI 的宣告周期系結問題。

  • 說明專案 Mvp 關係的實現邏輯。

  • 說明專案解決的痛點。

  • 分享 RxJava 的學習方法。

  • 整理出 Retrofit 簡易流程圖。

有不同意見的可以通過留言或者Issues,專案中重構部分的代碼註釋比較完善,便於你查閱,謝謝!

本專案 Github 地址:JudyKotlinMvp
https://github.com/Walkud/JudyKotlinMvp

已同步到看一看
赞(0)

分享創造快樂