Retrofit2.6开始增加了对Kotlin协程的支持,可以通过suspend函数进行异步调用。本文简单介绍一下Retrofit中协程的使用
data class
首先定义一个data class 模拟Api请求的response
data class Repos(
val id: Int,
val name: String
)
Retrofit
创建Retrofit实例
class ApiService {
private fun getRetrofit(): Retrofit {
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
return Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
}
fun get(): GithubApi {
val retrofit = getRetrofit()
return retrofit.create(GithubApi::class.java)
}
}
根据JakeWharton的建议,Json解析部分使用moshi替代gson,https://www.reddit.com/r/Kotlin/comments/exmp2s/json_to_kotlin_data_class/fgak5mc/
接下来对比一下使用协程与不使用协程时的Retrofit请求的区别
不使用协程
Api定义如下:
interface GithubApi {
@GET("/repos/octocat/Hello-World")
fun getRepos(): Call<Repos>
}
返回Call类型结果,通过enqueue插入队列等待回调处理
fun getRepos() {
private val api = ApiService().get()
api.getRepos().enqueue(object : Callback<Repos> {
override fun onResponse(call: Call<Repos>, response: Response<Repos>) {
// 成功逻辑
}
override fun onFailure(call: Call<Repos>, t: Throwable) {
// 失败逻辑
}
})
}
使用协程
使用suspend定义Api如下
interface GithubApi {
@GET("/repos/octocat/Hello-World")
suspend fun getReposWithCoroutine(): Repos
}
无需使用Call类型返回结果,直接返回 data class类型,结果的处理如下:
fun getReposWithCoroutine() {
private val api = ApiService().get()
viewModelScope.launch {
try {
val repos = api.getReposWithCoroutine()
// 成功逻辑
}
catch (e: Exception) {
// 失败逻辑
}
}
}
无需回调,可以同步处理结果,增加了try...catch为处理失败逻辑
ViewModelScope
为了调用suspend方法,需要提供一个CoroutineScope,如果实在ViewModel中进行api请求,可以像实例中那样使用ktx提供的viewModelScope,viewModelScope可以帮助我们在viewModel的onCleared时自动进行job的cancel,否则需要在手动cancel。
不在ViewModel中使用,例如在Activity中使用时,可以如下调用
CoroutineScope(Dispatchers.Main).launch {
// ...
}