Kotlin 版 MVP 基礎框架構建

簡介

快速搭建 Kotlin+MVP+RxJava+Retrofit+EventBus 的框架,方便快速開發新項目、減小開發成本,讓所寫的代碼更加簡潔,讓開發者只須要關注業務的實現。java

代碼結構

1. View 層的基類封裝

  • BaseActivityBaseFragment 是抽象類,封裝了佈局文件 ID 、初始化 View 、初始化數據、開始請求、是否使用 EventBus 、狀態欄等;
  • BaseMvpActivityBaseMvpFragment 分別繼承 BaseActivityBaseFragment 並實現了 IView 接口,將 MVP 基礎架構封裝起來;注:若是想使用 MVP 架構就繼承 BaseMvpActivity 或者 BaseMvpFragment ,若是不適用 MVP 架構就繼承 BaseActivity 或者 BaseFragment
  • BaseMvpTitleActivity 繼承 BaseMvpActivity ,簡單了封裝了 Toolbar,可擴展 。

2. ext 相關的封裝(主要用到了 Kotlin 擴展函數)

  • 封裝 logeshowToastshowSnackMsgsssss 等通用方法,項目中能夠直接調用;
  • sssss ,這兩個方法主要是對網絡請求的統一封裝,使用起來很是方便(亮點);
mModel?.getBanners()?.ss(mModel, mView) {
    mView?.showBanners(it.data)
}
addDisposable(
    mModel?.getBanners()?.sss(mView) {
        mView?.showBanners(it.data)
    }
)
複製代碼

這裏貼上 sssss 方法的代碼(這兩個方法用起來真的太爽了):git

fun <T : BaseBean> Observable<T>.ss(
    model: IModel?,
    view: IView?,
    isShowLoading: Boolean = true,
    onSuccess: (T) -> Unit
) {
    this.compose(SchedulerUtils.ioToMain())
        .retryWhen(RetryWithDelay())
        .subscribe(object : Observer<T> {
            override fun onComplete() {
                view?.hideLoading()
            }
            override fun onSubscribe(d: Disposable) {
                if (isShowLoading) {
                    view?.showLoading()
                }
                model?.addDisposable(d)
                if (!NetWorkUtil.isConnected()) {
                    view?.showDefaultMsg("當前網絡不可用,請檢查網絡設置")
                    d.dispose()
                    onComplete()
                }
            }
            override fun onNext(t: T) {
                when {
                    t.errorCode == ErrorStatus.SUCCESS -> onSuccess.invoke(t)
                    t.errorCode == ErrorStatus.TOKEN_INVAILD -> {
                        // Token 過時,從新登陸
                    }
                    else -> view?.showDefaultMsg(t.errorMsg)
                }
            }
            override fun onError(t: Throwable) {
                view?.hideLoading()
                view?.showError(ExceptionHandle.handleException(t))
            }
        })
}
複製代碼
fun <T : BaseBean> Observable<T>.sss(
    view: IView?,
    isShowLoading: Boolean = true,
    onSuccess: (T) -> Unit
): Disposable {
    if (isShowLoading) {
        view?.showLoading()
    }
    return this.compose(SchedulerUtils.ioToMain())
        .retryWhen(RetryWithDelay())
        .subscribe({
            when {
                it.errorCode == ErrorStatus.SUCCESS -> onSuccess.invoke(it)
                it.errorCode == ErrorStatus.TOKEN_INVAILD -> {
                    // Token 過時,從新登陸
                }
                else -> view?.showDefaultMsg(it.errorMsg)
            }
            view?.hideLoading()
        }, {
            view?.hideLoading()
            view?.showError(ExceptionHandle.handleException(it))
        })
}
複製代碼

3. 網絡通信通用類

  • 封裝 RetrofitFactory 來構建不一樣 baseUrlRetrofitService注:項目中 baseUrl 不少的狀況下,不建議使用,建議從新封裝) ;
  • 封裝 cookie 相關、統一的異常處理、 CacheInterceptorHeaderInterceptorSaveCookieInterceptor 等;
  • 封裝 請求重連 操做,詳情請見類 RetryWithDelay
object MainRetrofit : RetrofitFactory<MainApi>() {
    override fun baseUrl(): String = Constant.BASE_URL
    override fun getService(): Class<MainApi> = MainApi::class.java
}
interface MainApi {
    @GET("/banner/json")
    fun getHomeBanner(): Observable<HttpResult<MutableList<Banner>>>
}
複製代碼

4. MVP 基礎架構

MVP 便是 Model , View , Presenter 三層,把 Activity 中的 UI 邏輯抽象成 View 接口,把業務邏輯抽象成 Presenter 接口, Model 類仍是原來的 Model ,實現了 Model 層和 View 層徹底解耦。github

用戶觸發 V 層事件, V 層把事件通知 P 層, P 層通知 M 層處理這個事件, M 層處理完以後把結果發送給 P 層, P 層再發送給 V 層,最後 V 層作出相應的處理,這是 MVP 架構的一整套流程。json

  • M 層:模型層,負責數據的請求、解析、過濾等操做;
  • V 層:視圖層,負責視圖部分展現、視圖時間處理, ActivityFragmentDialogViewGroup 等呈現視圖的組件均可以承擔該角色;
  • P 層:模型層和視圖層交互的橋樑。
MVP 架構的優缺點

A. 優勢bash

  • 模塊職責劃分明顯,層次清晰,接口功能清晰;服務器

  • Model層和View層分離,解耦.修改 View 而不影響 Modelcookie

  • 功能複用度高,方便.一個 Presenter 能夠複用於多個 View ,而不用更改 Presenter 的邏輯;網絡

  • 有利於測試驅動開發,之前的 Android 開發是難以進行單元測試;架構

  • 若是後臺接口還未寫好,但已知返回數據類型的狀況下,徹底能夠寫出此接口完整的功能。框架

B. 缺點

  • MVP 中接口過多;

  • 每個功能,相比於 MVC 要多寫好幾個文件;

  • 若是某一個界面中須要請求多個服務器接口,這個界面文件中會實現不少的回調接口,致使代碼繁雜;

  • 若是更改了數據源和請求中參數,會致使更多的代碼修改;

  • 額外的代碼複雜度及學習成本。

5. rx 相關

  • 封裝 SchedulerUtils 工具類、 IoMainScheduler 等;
  • BaseObserverBaseSubscriberResourceObserverResourceSubscriber 通用封裝。

6. 工具類和幫助類

  • 封裝 Preference 類,主要採用了 kotlin 委託屬性和 SharedPreference 的實例;
  • 封裝 StatusBarUtil (適配狀態欄) 、 KeyBoardUtil (鍵盤相關) 、 NetWorkUtil (網絡相關) 、 RomUtil (手機ROM相關) 、 FileProvider7 (7.0手機文件適配) 等。

7. 自定義控件

  • 封裝 ToastLoadingViewOnNoDoubleClickListener (防止連續點擊)。

如何使用?

只須要五步就能夠實現 MVP 架構。

第一步:導入baselibs庫

Clone or Download 後導入 baselibs 庫,再根據需求自行修改便可。

第二步:定義一個Contract

須要定義一個 Contract 接口,來抽象 ViewPresenterModel 的方法,而且它們須要分別繼承 IViewIPresenterIModel 接口。

案例: MainContract

interface MainContract {
    interface View : IView {
        fun showBanners(banners: MutableList<Banner>)
    }
    interface Presenter : IPresenter<View> {
        fun getBanner2()
    }
    interface Model : IModel {
        fun getBanners(): Observable<HttpResult<MutableList<Banner>>>
    }
}
複製代碼
第三步:建立一個Model接口的實現類,須要繼承 BaseModel 類 並實現Model接口

案例: MainModel

class MainModel : BaseModel(), MainContract.Model {
    override fun getBanners(): Observable<HttpResult<MutableList<Banner>>> {
        return MainRetrofit.service.getHomeBanner()
    }
}
複製代碼
第四步:建立一個Presenter接口的實現類,須要繼承 BasePresenter<M : IModel, V : IView> 並實現 MainContract.Presenter 接口

案例: MainPresenter

class MainPresenter : BasePresenter<MainContract.Model, MainContract.View>(), MainContract.Presenter {
    override fun createModel(): MainContract.Model? = MainModel()
    override fun getBanner2() {
        mModel?.getBanners()?.ss(mModel, mView) {
            mView?.showBanners(it.data)
        }
    }
}
複製代碼
第五步:建立一個View的接口實現類,這是一個Activity或者Fragment,須要繼承BaseMvpActivity<in V : IView, P : IPresenter> 或者 BaseMvpFragment<in V : IView, P : IPresenter> 並實現 View 接口

案例:MainActivity

class MainActivity : BaseMvpTitleActivity<MainContract.View, MainContract.Presenter>(), MainContract.View {
    override fun attachChildLayoutRes(): Int = R.layout.activity_main
    override fun createPresenter(): MainContract.Presenter = MainPresenter()
    override fun initView() {
    }
    override fun initData() {
    }
    override fun start() {
        mPresenter?.getBanner2()
    }
    override fun showBanners(banners: MutableList<Banner>) {
        tv_result.text = banners.toString()
    }
}
複製代碼

至此, Kotlin 基礎框架已經搭建完成,若有錯誤之處還請指正。

最後

完整的項目地址:github.com/iceCola7/Ko…

相關文章
相關標籤/搜索