關注 秉心說,公衆號後臺回覆
玩安卓
便可獲取 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-ViewModel
,View
指綠色的 Activity/Fragment
,主要負責界面顯示,不負責任何業務邏輯和數據處理。Model
指的是 Repository
包含的部分,主要負責數據獲取,來組本地數據庫或者遠程服務器。ViewModel
指的是圖中藍色部分,主要負責業務邏輯和數據處理,自己不持有 View
層引用,經過 LiveData
向 View
層發送數據。Repository
統一了數據入口,無論來自數據庫,仍是服務器,統一打包給 ViewModel
,我在項目中並無使用數據庫,而是使用緩存代替。github
除了 MMVM
之外,我用 協程
代替了 RxJava
。這裏先不論協程和 RxJava 孰優孰劣,只是用慣了 RxJava,協程的確會給你耳目一新的感受,用同步的方式寫異步代碼。在 Java 中並無協程的概念,Kotlin 中在編譯期實現了協程,經過相似狀態機的實現。協程能夠看作是輕量級的線程,不會存在上下文切換的帶來的性能損耗,理論上是比線程效率更高的。數據庫
下面以登陸頁面 LoginActivity
爲例,看一下數據流程。編程
@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
方法。緩存
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()
提供了統一的響應錯誤處理。微信
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 進行綁定,上面代碼中的 mLoginUser
和 errMsg
就是 ViewModel 層 「發射」 過來的數據。關於數據綁定,我並無使用 DataBinding
,這個純粹是我的喜愛了,我只是不喜歡 DataBinding 帶來的代碼不易讀。
相對 Mvp 繁多的接口來講,我的感受 Mvvm 的數據流更加清晰。搭配 Kotlin 和協程的使用,進一步簡化代碼。下面是一些項目截圖:
項目地址點這個: 傳送門,記得切換到 mvvm-kotlin
分支 ,歡迎帶來 star 和 issue 丟過來 !
推薦一下個人另外一個應用,Box —— 個人開發助手,添加了查看 logcat 的功能。
最後,也歡迎你們關注個人公衆號 秉心說,話說公號關注人數還沒掘金多,後續會繼續 《走進 JDK 系列》以及 Android 相關知識的分享,歡迎你們掃碼關注!有任何關於 Java/Android 的問題也能夠加個人我的微信 bingxinshuo_
。
公衆號後臺回覆 玩安卓
便可獲取 Wanandroid 安裝包。
文章首發微信公衆號:
秉心說
, 專一 Java 、 Android 原創知識分享,LeetCode 題解,歡迎關注!