Retrofit2.6でsuspend関数がサポート
Retrofit2.6でsuspendがサポートされ、HTTPリクエストをcoroutineを使って書くことができるようになりました!
New: Support suspend modifier on functions for Kotlin! This allows you to express the asynchrony of HTTP requests in an idiomatic fashion for the language.
retrofit - Change Log
Retrofit 2.6以前と比較してみたいと思います。
こちらにサンプルコードがあるので、参考にしていただければー!
Retrofit 2.6以前で通信を非同期処理
Retrofitの2.6以前で非同期処理を行う場合は、enqueueを使用します。
具体的にはCallを戻り値に設定して
interface EmployeeApi {
@GET("employees")
fun getEmployeeWithCall(): Call<List<Employee>>
}
この戻り値を利用してenqueueを呼び出します。
enqueueにコールバック(コード例ではCustomCallBack)を渡して、成功時にはonResponse、失敗時にはonFailureが実行されます。
class EmployeeService {
fun getAsyncEmployeeWithCall() {
service.getEmployeeWithCall().enqueue(CustomCallBack())
service.getEmployeeWithCall().enqueue(CustomCallBack())
}
private class CustomCallBack: Callback<List<Employee>>{
override fun onResponse(call: Call<List<Employee>>, response: Response<List<Employee>>) {
// TODO やりたい処理
}
}
override fun onFailure(call: Call<List<Employee>>, t: Throwable) {
// TODO エラーハンドリング
}
}
}
Retrofit2.6で通信を非同期処理
Retrofit2.6ではHTTPリクエストを送るメソッドをsuspendにすることができるようになります。
この際、戻り値はCallではなくResponseを指定します。
interface EmployeeApi {
@GET("employees")
suspend fun getEmployeesWithResponse(): Response<List<Employee>>
}
呼び出し側は、coroutineの要領で記述できます。
class EmployeeService {
fun getAsyncEmployeeWithSuspendFunc() {
runBlocking {
val job1 = async { service.getEmployeesWithResponse() }
val job2 = async { service.getEmployeesWithResponse() }
val res1: Response<List<Employee>> = job1.await()
val res2: Response<List<Employee>> = job2.await()
println(res1.body()?.forEach { println(it) })
println(res2.body()?.forEach { println(it) })
}
}
}
直感的に非同期処理をかけるのでいいですね。
また、Responseで返されるので色々とレスポンスのメタデータがいじれて便利です。
// リクエストを取得したり・・・
res1.raw().request()
// レスポンスのヘッダーを確認したり・・・
res1.headers().toMultimap().forEach {
println("${it.key}: ${it.value}")
}
まとめ
coroutine対応のおかげで、ぱっと見で何をしているかわかりやすくなった気がします。
ただ、coroutineび知識はまだまだなので、何かご指摘があればいただけると嬉しいです。