Kotlin的魔能機甲——KtArmor(一)

前言

學習了Kotlin有一段時間了, 每次寫項目/Demo的時候, 老是用到網絡請求MVPMVVM經常使用工具類通用自定義View, 索性把這些整合到一塊兒, 搭成一個Android的腳手架——KtArmor.java

什麼是KtArmor ?

KtArmor 寓意着 爲Android 賦予戰鬥裝甲, 方便開發者快速進行Android 開發。節約開發者開發時間。爲了知足開發者需求, 我整合了兩個分支, 分別對應着 MVP, MVVM.git

  • MVP分支
    • 架構模式: MVP + Kotlin
    • 網絡請求: Retrofit + Okhttp + Coroutine + RxJava
    • 功能
      • 基本BaseActivityBaseFragmentToolbarActivity封裝
      • MVP框架封裝 MvpActivityMvpFragmentBasePresenterBaseModel封裝
      • 網絡請求封裝 BaseOkHttpClientBaseRetrofitRetrofitFactory
      • 經常使用控件PlaceHolderView(佔位佈局)LoadingView(加載框)
      • 經常使用擴展封裝(SharedPreferencesStartActivityLogToast(不重複顯示))等
      • MVP代碼模板(ActivityPresenterContractModel)生成插件
      • ....
  • MVVM分支
    架構模式: MVVM+ Androidx + Kotlin + LiveData + ViewModel
    網絡請求: Coroutines + Retrofit + Okhttp

MVP框架引入

先在 build.gradle(Project:XXXX) 的 repositories 添加:github

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}
複製代碼

而後在 build.gradle(Module:app) 的 dependencies 添加:api

implementation 'com.github.hyzhan43:KtArmor:mvp-1.0.4'  // 根據github 引入最新版本便可
複製代碼

快速上手

在Application 中初始化KtArmor 框架。新建一個application 類, 如 BaseApplication, 在 BaseApplication 中, 調用KtArmor的 init 方法, 進行初始化, 參數以下:bash

  • 第一個參數是application,
  • 第二個參數是對應RetrofitConfig 配置。
class BaseApplication: Application(){

    override fun onCreate() {
        super.onCreate()

        // 初始化KtArmor
        KtArmor.init(this, MyRetrofitConfig())
    }
}
複製代碼

再新建一個 RetrofitConfig 配置類, 繼承 BaseRetrofitConfig. 並複寫 baseUrl 屬性, 添加本身的 baseUrl。網絡

class MyRetrofitConfig : BaseRetrofitConfig() {

    override val baseUrl: String
        get() = API.BASE_URL
}
複製代碼

這樣你就建立好了一個擁有Kotlin + Retrofit + Okhttp + Coroutine項目了。而後就能夠愉快編寫本身的業務代碼了(●'◡'●)架構

Login 示例

一、LoginContract

咱們先從簡單登陸流程來熟悉一下KtArmor。首先編寫 LoginContract, 代碼以下:app

interface LoginContract {

    interface View : BaseContract.View {
        fun accountEmpty(msg: Int)
        fun passwordEmpty(msg: Int)
        fun loginSuc(loginRsp: LoginRsp)
    }

    interface Presenter : BaseContract.Presenter {
        fun login(account: String, password: String)
    }
}
複製代碼

二、LoginActivity

而後新建一個LoginActivity, 繼承 MvpActivity 並傳遞對應 LoginContract.Presenter 泛型,實現 LoginContract.View 接口, 代碼以下:框架

class LoginActivity : MvpActivity<LoginContract.Presenter>(), LoginContract.View {

    override fun getLayoutId(): Int = R.layout.activity_login

    override fun bindPresenter(): LoginContract.Presenter = LoginPresenter(this)

    override fun initListener() {
        super.initListener()

        mBtnLogin.setOnClickListener {
            mTilAccount.isErrorEnabled = false
            mTilPassword.isErrorEnabled = false
            
            // 發起登陸請求
            presenter.login(mEtAccount.str(), mEtPassword.str())
        }
    }

    override fun accountEmpty(msg: Int) {
        mTilAccount.isErrorEnabled = true
        mTilAccount.requestFocus()
        mTilAccount.error = getString(msg)
    }

    override fun passwordEmpty(msg: Int) {
        mTilPassword.isErrorEnabled = true
        mTilPassword.requestFocus()
        mTilPassword.error = getString(msg)
    }

    override fun loginSuc(loginRsp: LoginRsp) {
        toast("登錄成功!")
    }
}
複製代碼
  • bindPresenter 方法返回 LoginPresenter 實例。
  • getLayoutId方法 返回LoginActivity 佈局id。

這裏 activity_login 裏面是簡單的 TextInputEditText,調用presenter, 發起登陸請求。傳遞帳號和密碼。其中 str() 爲 TextView 擴展方法。maven

  • str() 爲擴展方法
// 獲取text內容
fun TextView.str(): String {
    return this.text.toString()
}
複製代碼

三、LoginPresenter

而後咱們再看看對應 LoginPresenter 實現, 繼承 BasePresenter,並傳遞對應 LoginContract.View

class LoginPresenter(view: LoginContract.View) : BasePresenter<LoginContract.View>(view), LoginContract.Presenter {

    override fun login(account: String, password: String) {

        if (account.isEmpty()) {
            view?.accountEmpty(R.string.account_empty)
            return
        }

        if (password.isEmpty()) {
            view?.passwordEmpty(R.string.password_empty)
            return
        }

        launchUI({
            view?.showLoading()
            val response = LoginModel.login(account, password)

            // 正常返回結果處理
            if (response.isSuccess()) {
                response.data?.let { view?.loginSuc(it) }
            } else {
                view?.showError(response.errorMsg)
            }
        }, {
            // TODO 異常處理
        })
    }
}
複製代碼

在這裏, 咱們採用協程來實現切換線程操做。在 launchUI() 方法裏面啓動了一個 UI 協程,在這裏調用 LoginModel 真正發起網絡請求操做。

四、LoginModel

object LoginModel : BaseModel() {

    suspend fun login(account: String, password: String): BaseResponse<LoginRsp> {
        return launchIO { ApiManager.apiService.loginAsync(account, password).await() }
    }
}
複製代碼

一樣,LoginModel 須要繼承 BaseModel(),並調用 launchIO 進行線程切換。切換到 IO線程 經過ApiManager.apiService 發起網絡請求。而後調用 await() 返回結果。這裏 ApiService 經過 RetrofitFactory建立, 傳入 Service class。

object ApiManager {

    val apiService by lazy {
        RetrofitFactory.instance.create(ApiService::class.java)
    }
}
複製代碼
interface ApiService {

    @POST(API.LOGIN)
    fun loginAsync(@Query("username") username: String, @Query("password") password: String): Deferred<BaseResponse<LoginRsp>>
}
複製代碼

以上就是登陸的全過程。看到這裏,編寫一個簡單Login功能須要新建四個類,有點麻煩。有沒有更便捷的方法的。那確定!KtArmor 框架還有與之對應 KtArmor-MVP 插件,幫助開發者快速生成對應模板代碼(ActivityPresenterContractModel)。

未完待續

這是KtArmor開篇的第一篇。大概講解了KtArmor基本用法。後續會詳細講解框架的使用、以及插件的使用。至於KtArmor-MVVM 版目前還在測試階段。後續也會陸續更新。敬請期待吧!
着急的小夥伴能夠直接查看下文源碼~

最後

KtArmor 框架是一款小而美的框架,也是我我的經驗的積累, 總結。若有不妥, 望各位大佬指出。歡迎你們 pr交易, 一塊兒交流學習。

KtArmor-MVP 源碼傳送門

Kotlin的魔能機甲——KtArmor插件篇(二)

Kotlin的魔能機甲——KtArmor(三)

下次再見

相關文章
相關標籤/搜索