真香!Kotlin+MVVM+LiveData+協程 打造 Wanandroid!

關注 秉心說,公衆號後臺回覆 玩安卓 便可獲取 Wanandroid 安裝包。java

Wanandroid 是鴻洋鴻大大的安卓開源知識網站,包含最新博文,最新項目,經常使用工具,公衆號文章收錄等等功能,同時也開源了全部 API 接口,方便你們打造本身的 Wanandroid 客戶端。Github 上關於 Wanandroid 的客戶端也層出不窮,Java的,Kotlin 的,Flutter 的,Mvp 的,MVMM 的,各類各樣,可是還沒看到 Kotlin+MVVM+LiveData+協程 版本的,加上最近正在看 MVVM 和 LiveData,就着手把我以前寫的 Mvp 版本的 Wanandroid 改形成 MVVM,項目地址 。注意,mater 分支是年久失修的 Mvp 版本,不必定保證能夠運行。mvvm-kotlin 分支是最新代碼。android

關於 MVVM,你們應該也比較熟悉了,上一張 MVVM 經典架構圖:git

Model-View-ViewModelView 指綠色的 Activity/Fragment,主要負責界面顯示,不負責任何業務邏輯和數據處理。Model 指的是 Repository 包含的部分,主要負責數據獲取,來組本地數據庫或者遠程服務器。ViewModel 指的是圖中藍色部分,主要負責業務邏輯和數據處理,自己不持有 View 層引用,經過 LiveDataView 層發送數據。Repository 統一了數據入口,無論來自數據庫,仍是服務器,統一打包給 ViewModel ,我在項目中並無使用數據庫,而是使用緩存代替。github

除了 MMVM 之外,我用 協程 代替了 RxJava。這裏先不論協程和 RxJava 孰優孰劣,只是用慣了 RxJava,協程的確會給你耳目一新的感受,用同步的方式寫異步代碼。在 Java 中並無協程的概念,Kotlin 中在編譯期實現了協程,經過相似狀態機的實現。協程能夠看作是輕量級的線程,不會存在上下文切換的帶來的性能損耗,理論上是比線程效率更高的。數據庫

下面以登陸頁面 LoginActivity 爲例,看一下數據流程。編程

Model

@POST("/user/login")
fun login(@Field("username") userName: String, @Field("password") passWord: String): Deferred<WanResponse<User>> 複製代碼

這是登陸 Api 接口。api

class LoginRepository : BaseRepository() {

    suspend fun login(userName: String, passWord: String): WanResponse<User> {
        return apiCall { WanRetrofitClient.service.login(userName, passWord).await() }
    }
    
}
複製代碼

LoginRepository 中定義具體的登陸邏輯,經過 Retrofit 調用登陸接口,返回 WanResponse<User>。注意,要在協程中使用,因此定義爲 suspend 方法。緩存

ViewModel

class LoginViewModel : BaseViewModel() {
    val mLoginUser: MutableLiveData<User> = MutableLiveData()
    val errMsg: MutableLiveData<String> = MutableLiveData()
    private val repository by lazy { LoginRepository() }

    fun login(userName: String, passWord: String) {
        launch {
            val response = withContext(Dispatchers.IO) { repository.login(userName, passWord) }
            executeResponse(response, { mLoginUser.value = response.data }, { errMsg.value = response.errorMsg })
        }
    }
}
複製代碼

LoginViewModel 持有 LoginRepository,並經過它執行具體登陸邏輯,這一塊使用協程執行。返回結果經過 executeResponse() 方法處理,這是我本身封裝的方法:服務器

suspend fun executeResponse(response: WanResponse<Any>, successBlock: suspend CoroutineScope.() -> Unit, errorBlock: suspend CoroutineScope.() -> Unit) {
        coroutineScope {
            if (response.errorCode == -1) errorBlock()
            else successBlock()
        }
    }
複製代碼

Kotlin 的一些函數式編程語言特性會給咱們的開發帶來一些便利。executeResponse() 提供了統一的響應錯誤處理。微信

View

mViewModel.apply {
        mLoginUser.observe(this@LoginActivity, Observer {
            dismissProgressDialog()
            startActivity(MainNormalActivity::class.java) finish() }) errMsg.observe(this@LoginActivity, Observer {
            dismissProgressDialog()
            it?.run { toast(it) }
        })
    }
複製代碼

最後就是 LoginActivity 表明的 View 層了,View 層和 ViewModel 層經過 LiveData 進行綁定,上面代碼中的 mLoginUsererrMsg 就是 ViewModel 層 「發射」 過來的數據。關於數據綁定,我並無使用 DataBinding,這個純粹是我的喜愛了,我只是不喜歡 DataBinding 帶來的代碼不易讀。

相對 Mvp 繁多的接口來講,我的感受 Mvvm 的數據流更加清晰。搭配 Kotlin 和協程的使用,進一步簡化代碼。下面是一些項目截圖:

項目地址點這個: 傳送門,記得切換到 mvvm-kotlin 分支 ,歡迎帶來 star 和 issue 丟過來 !

推薦一下個人另外一個應用,Box —— 個人開發助手,添加了查看 logcat 的功能。

最後,也歡迎你們關注個人公衆號 秉心說,話說公號關注人數還沒掘金多,後續會繼續 《走進 JDK 系列》以及 Android 相關知識的分享,歡迎你們掃碼關注!有任何關於 Java/Android 的問題也能夠加個人我的微信 bingxinshuo_

公衆號後臺回覆 玩安卓 便可獲取 Wanandroid 安裝包。

文章首發微信公衆號: 秉心說 , 專一 Java 、 Android 原創知識分享,LeetCode 題解,歡迎關注!

相關文章
相關標籤/搜索