近日 Retrofit 更新到了 2.6.0 版本,內置了對 Kotlin Coroutines 的支持,進一步簡化了使用 Retrofit 和協程來進行網絡請求的過程。其實縱觀編程語言的發展歷史,從彙編到 C/C++,從 Java,OC 到 Swift,Kotlin,甚至被歸入教材的 Python,都有一個共同的特色。隨着 CPU 性能的愈來愈強悍,提升生產力彷佛都成了現代高級編程語言的共同目標。Kotlin 就是一個好例子,作一樣的事情,完成一樣的功能,Java 的確須要更多的代碼,Kotlin 也的確給 Android 開發提高了效率。特別是在異步任務方面,Kotlin 提供了協程,而這是 Java 所不具有的。關於 Kotlin Coroutines 的介紹,能夠閱讀我以前的三篇譯文:java
在 Android 上使用協程(一):Getting The Backgroundandroid
回到正題,本篇主要介紹 Retrofit 2.6.0 版本中協程的使用方式,不會過多涉及原理。我以我本身的 wanandroid 應用爲例進行改造,源代碼中 Retrofit 版本是 2.4.0
。這個 wanandroid 是基於 Kotlin + 協程 + LiveData + MVVM
實現的,具體架構可見個人文章 真香!Kotlin+MVVM+LiveData+協程 打造 Wanandroid! ,我的以爲代碼仍是比較清晰的,很適合做爲 Kotlin 的 入門項目。編程
在介紹如何使用 Retrofit 2.6.0
以前,咱們先來看一下老版本的 Retrofit 是如何基於 Kotlin Coroutines 工做的,以登陸接口爲例。api
首先在 WanService 接口中做以下定義:bash
@POST("/user/login")
fun login(@Field("username") userName: String, @Field("password") passWord: String): Deferred<WanResponse<User>>
複製代碼
注意這裏使用的返回值是 Deferred<T>
對象,這就意味着使用的時候要經過 await
來獲取返回值。那麼如何讓 Retrofit 直接返回 Deferred<T>
呢?使用的也是 JakeWharton 的開源庫:微信
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
複製代碼
在構建 Client 的時候添加上這個適配器:網絡
...
.addCallAdapterFactory(CoroutineCallAdapterFactory.invoke())
...
複製代碼
而後給 LoginRepository 提供一個 suspend 方法:架構
suspend fun login(userName: String, passWord: String): WanResponse<User> {
return apiCall { WanRetrofitClient.service.login(userName, passWord).await() }
}
複製代碼
這裏使用 await
來獲取 Deferred<T>
的返回值。
最後在 LoginViewModel 中是這樣調用的:
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 })
}
}
複製代碼
launch()
方法作了簡單的封裝,感興趣的同窗能夠到源碼中看一下。
以上就是在 Retrofit 2.4.0
中使用協程的基本方式了,其實代碼也很簡潔。而 Retrofit 2.6.0
讓這一切更加簡單!就讓咱們一睹爲快吧!
Talking is cheap, show me the code !
仍是上面的登陸接口,基於 Retrofit 2.6.0
來改造一下。
第一步,修改 Retrofit 依賴。
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
複製代碼
第二步,修改 WanService
中接口的定義。
@POST("/user/login")
suspend fun login(@Field("username") userName: String, @Field("password") passWord: String): WanResponse<User>
複製代碼
看到區別了嗎?首先,再也不返回 Deferred<T>
對象,而是直接返回咱們須要的 WanResponse
對象。其次,使用了 suspend
來修改方法,標記這是掛起函數。
第三步,修改 LoginRepository
中方法定義。
suspend fun login(userName: String, passWord: String): WanResponse<User> {
return apiCall { WanRetrofitClient.service.login(userName, passWord) }
}
複製代碼
與以前的版本相比,這裏不須要調用 await
方法了。其實並非不調用了,而是 Retrofit 幫助咱們自動調用了。
最後別忘了去除以前添加的 kotlin-coroutines-adapter
,由於咱們再也不須要人工返回 Deferred<T>
對象,也再也不須要手動調用 await
了。
...
//.addCallAdapterFactory(CoroutineCallAdapterFactory.invoke())
...
複製代碼
至此,基於 Retrofit 2.6.0
版本的改造就已經完成了。個人 Wanandroid 項目已經完成所有修改,具體修改內容可見 commit。
隨着 Kotlin 成爲 Android 開發的首選語言,愈來愈多的新特性都將在 Kotlin 上優先實現。協程做爲 Kotlin 的異步利器,很值得咱們學習。若是你尚未入手,那麼,從個人 Wanandroid 開始吧 !
文章首發微信公衆號:
秉心說
, 專一 Java 、 Android 原創知識分享,LeetCode 題解。更多相關知識,掃碼關注我吧!