Kotlin的聖光機甲——KtArmor通用流程篇 (二)

前言

前一篇中,介紹了 KtArmor—MVVM 簡單的使用方法,可是這每每不是所有。git

在持續迭代、維護下,發現功能越寫越多,也相應複雜起來。github

因此後續,我儘量編寫詳細 說明文檔,而且在源碼編寫 註釋api

廢話很少說,進入正文。網絡

ViewModel

回到上文所說的 Login 示例,咱們在 LoginViewModel,經過quickLaunch DSL 方式,發起網絡請求。以下代碼所示:框架

class LoginViewModel : BaseViewModel<LoginRepository>() {

    val loginData = MutableLiveData<LoginRsp>()

    fun login(account: String, password: String) {
        
    		...省略其餘代碼

        // DSL 方式發起 網絡請求
        quickLaunch<LoginRsp> {

            onStart { showLoading() }
            
            request { repository.login(account, password) }

            onSuccess { loginData.value = it }
        }
    }
}
複製代碼

quickLaunch 方法,需傳入範型( 返回值類型),即調用 repository.login(account, password) 返回值類型, 且必須實現 KResponse 接口,以下代碼所示:ide

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

KResponse

因爲 quickLaunch DSL 方式默認實現了 Success,Failure 邏輯處理,而且進行相應回調。因此 Retrofit 的 api service 返回的 BaseResponse,必須實現 KResponse 接口post

KResponse 實現以下:

data class BaseResponse<T>(var data: T?,
                           var errorCode: Int = -1,
                           var errorMsg: String = "") : KResponse<T> {

    override fun isSuccess(): Boolean = errorCode == 0

    override fun getKData(): T? = data

    override fun getKMessage(): String? = errorMsg
}
複製代碼

以上是參考代碼,根據後臺接口返回的類型,新建一個 基類 Response(BaseResponse),實現 KResponse 接口,而且實現對應的方法學習

  • isSuccess(必須)
  • getKData(必須)
  • getKMessage(必須)
  • executeRsp
  • execute

其中 executeRsp,execute 默認實現了 默認的處理邏輯,以下所示優化

/** * 全局默認實現, 可根據自身業務 重寫execute方法 * @param error 如有錯誤的回調, 默認getKMessage(), 不然返回 Setting.MESSAGE_EMPTY * @param successResponse 成功的回調, 默認是返回 KResponse<T> */
fun executeRsp(successResponse: ((KResponse<T>) -> Unit)?, error: ((String) -> Unit)? = null) {

    if (this.isSuccess()) {
        successResponse?.invoke(this)
        return
    }

    (this.getKMessage() ?: Setting.MESSAGE_EMPTY).let { 
      error?.invoke(it) ?: Toasts.show(it) 
    }
}

/** * 全局默認實現, 可根據自身業務 重寫execute方法 * @param success 成功的回調, 默認是返回 getKData() * @param error 如有錯誤的回調, 默認getKMessage(), 不然返回 Setting.MESSAGE_EMPTY */
fun execute(success: ((T?) -> Unit)?, error: ((String) -> Unit)? = null) {

    if (this.isSuccess()) {
        success?.invoke(this.getKData())
        return
    }

    (this.getKMessage() ?: Setting.MESSAGE_EMPTY).let { 
      error?.invoke(it) ?: Toasts.show(it)
    }
}
複製代碼

以 execute 爲例,默認是 根據 isSuccess 判斷是否成功,而且 回調到 quickLaunch 方法的 onSuccess、onFailure 方法。開發者能夠根據自身需求,對 execute/executeRsp 方法重寫ui

你覺得這樣就完事了嗎?

擴展

通常狀況下,咱們獲取了 repository 返回的數據,在 onSuccess 方法處理本身的業務邏輯。

而後 遇到異常,會進行以下操做:

  • toast 顯示 message
  • print log。
  • hideLoading
  • ....

以下代碼所示:

quickLaunch<LoginRsp> {

    request { repository.login(account, password) }

    onSuccess { loginSuccessData.value = it }

    onFailure { loginFailData.value = it }

    onException { loginExceptionLiveData = it }
}
複製代碼

因爲 Activity 是經過觀察 ViewModel 中 liveData 數據變化,進而作 請求成功,請求失敗 等邏輯處理。

因此首先想到是 新增 三個 LiveData,來通知 Activity,可是每次請求,都須要如此操做,這時候須要封裝一下了。

方案

KtArmor-MVVM, 嘗試引入一個 複合 LiveData—— CommonLiveData,解決上面問題, 所謂 複合,本質就是 CommonLiveData,裏面包含 兩個LiveData,以下代碼所示:

class CommonLiveData<T> : MutableLiveData<T>() {

    val errorLiveData = MutableLiveData<String>()
    
    ... 省略其餘
}
複製代碼

ViewModel

在ViewModel 中 使用方式以下

val loginData = CommonLiveData<LoginRsp>()
            // 看這裏 ^^^^

quickLaunch<LoginRsp> {

    request { repository.login(account, password) }

    onSuccess { loginData.value = it }

    onFailure { loginData.failureMessage = it }

    onException { loginData.exception = it }
}

/** * 等同上面 quickLaunch */
superLaunch(loginData) {
    request { repository.login(account, password) }
}

/** * 等同上面 superLaunch */
superLaunchRequest(loginData) { repository.login(account, password) }
複製代碼

在原有基礎上,MutableLiveData,切換成 CommonLiveData

而且新增一個 superLaunch DSL 方法,簡化了 quickLaunch DSL 方法 的賦值操做

固然 你也能夠根據自身業務,重寫 onSuccess, onFailure, onException 等方法。

而後咱們再來看看 Activity,代碼上,就更加方便簡單明瞭。

Activity

class LoginActivity : AppCompatActivity(), IMvmActivity {
		
  	...省略其餘代碼

    override fun dataObserver() {
    
        // 正常 MutableLiveData 監聽
        viewModel.loginData.observe(this, Observer {
            toast("登陸成功")
        })
        
        // CommonLiveData 監聽
        quickObserve(loginViewModel.loginData) {
            onSuccess {
                toast("登陸成功")
            }

            onFailure { message ->
                toast(message)
            }

            onException { throwable ->
                toast(R.string.unkown_error)
                logd(msg)
            }
        }

        /** * CommonLiveData 監聽, 等同上面, 只監聽 Success 狀況 * onSuccess: 自定義實現 * onFailure: 默認 toast message (viewModel 傳遞過來的 message) * onException: 默認 toast "未知異常"(固定), 打印 log */
        quickObserveSuccess(loginViewModel.loginData) {
            toast("登陸成功")
        }
    }
}
複製代碼

仍是以 Login 示例,咱們在 LoginActivity 中,須要 observe, LoginViewModel 中的 loginData,來獲取 請求成功後的數據。

如果 使用了 CommonLiveData,則咱們只需調用 quickObservequickObserveSuccess,便可監聽到 ViewModel 傳遞過來的數據,進行相應的處理。

具體方法說明,都在上面代碼註釋所示。

自定義

看到這裏,可能有小夥伴會說了,你的默認實現,不符合個人業務,不喜歡,想要修改,怎麼辦。

沒問題!

KtArmor-MVVM 提供對應接口,給開發者進行自定義擴展

Activity

class MyActivityActuator : IActivityActuator {
    override fun <R> success(mvmView: IMvmView, data: R?) {
    }

    override fun failure(mvmView: IMvmView, message: String?) {
    }

    override fun exception(mvmView: IMvmView, throwable: Throwable?) {
    }

}
複製代碼

新建 MyActivityActuator, 而且實現 IActivityActuator 接口,自定義 quickObserve 默認處理邏輯。

ViewModel ,也是同理。實現 ILiveDataActuator 接口,自定義 superLaunch 默認處理邏輯

ViewModel

class MyLiveDataActuator : ILiveDataActuator() {
    override fun <R> success(liveData: CommonLiveData<R>, data: R?) {
    }

    override fun <R> failure(liveData: CommonLiveData<R>, message: String?) {
    }

    override fun <R> exception(liveData: CommonLiveData<R>, throwable: Throwable?) {
    }
}
複製代碼

最後別忘了,須要 配置到 KtArmor 中,這樣纔會生效!

class BaseApplication : Application() {
    override fun onCreate() {
        super.onCreate()

        // KtArmor 相關配置
        with(KtArmor){
            configActivityActuator(MyActivityActuator())
            configLiveDataActuator(MyLiveDataActuator())
        }
    }
}
複製代碼

小結

代碼總體實現上,相對簡單,遵循開源框架的 三部曲,使得框架 可全局配置,可局部配置。

後續想到更好的方案,在進行優化,

不知大家意向如何? 期待小夥伴們更好方案 : )

最後

KtArmor-MVVM 框架是一款小而美的框架,也是我我的經驗的積累, 總結,但願你們喜歡。

若是你有更好的建議歡迎 pr,issues 一塊兒交流學習。

若有不妥, 望各位大佬指出。

KtArmor-MVVM 源碼傳送門

相關文章

MVVM

MVP

下次再見

相關文章
相關標籤/搜索