Retrofit2.6开始增加了对Kotlin协程的支持,可以通过suspend函数进行异步调用。本文简单介绍一下使用Kotlin协程配合Retrofit使用,发起网络请求。

导入依赖

app的build文件中加入:

implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
  • 注意依赖版本

data class

定义一个结果类,可以与后端的数据保持一致

data class ResultData<T>(
val code: Int,
val message: String,
val data: T
)

Service

ArticleService是一个专门用来写请求方法的接口,不用我们实现。

interface ArticleService {
@GET("article/get/{id}")
suspend fun getArticleById(@Path("id") id: Long): ResultData<Article>
}
  • 注意,请求路径前不加/,因为BASE_URL中已经加了

Retrofit实例

/**
* 创建Retrofit提供API Service
*/
object RetrofitClient {

const val BASE_URL = "http://192.168.2.194:8080/" // http://localhost:8080/

val okHttpClient = OkHttpClient.Builder()
.callTimeout(30, TimeUnit.SECONDS)
.build()

val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build()

val articleService = retrofit.create(ArticleService::class.java)

}

在ViewModel中使用

class ArticleViewModel : ViewModel() {

val article by lazy {
MutableLiveData<Article>()
}

fun getArticle(id: Long) {
viewModelScope.launch {
val article = RetrofitClient.articleService.getArticleById(id)
contentList.value = articleList.data
Log.d("ViewPagerViewModel", "getArticle: $article")
}
}
}

ViewModelScope

为了调用suspend方法,需要提供一个CoroutineScope,如果是在ViewModel中进行api请求,可以像实例中那样使用ktx提供的viewModelScope,viewModelScope可以帮助我们在viewModel的onCleared时自动进行job的cancel,否则需要在手动cancel。

不在ViewModel中使用,例如在Activity中使用时,可以如下调用

CoroutineScope(Dispatchers.Main).launch {
// ...
}

不使用协程

Service

interface ArticleService {
@GET("article/get/{id}")
fun getArticleById(@Path("id") id: Long): Call<Article>
}

返回Call类型结果,通过enqueue插入队列等待回调处理

fun getArticle(id: Long) {
private val api = RetrofitClient.articleService
api.getArticleById().enqueue(object : Callback<Article> {
override fun onResponse(call: Call<Article>, response: Response<Article>) {
// 成功逻辑
}
override fun onFailure(call: Call<Article>, t: Throwable) {
// 失败逻辑
}
})
}