はじめに
Android開発における代表的なHTTP通信ツールとして、RetrofitとKtorの2つがあると思います。基本的な機能は当然同じなのですが、ではこの2つにはどのような違いがあり、またどう使い分ければ良いのかについて簡潔に紹介していきます。
Retrofitについて
Retrofitは、Square社が開発しているライブラリで、長年Android開発現場で使われてきたものになります。Retrofitの特徴は、アノテーションベースで記述する点と、インターフェースを定義するだけで実装をライブラリが自動でやってくれる点です。例えば「ユーザー情報を取得する」処理をRetrofitで記述してみると以下のようになります。
interface ApiService {
@GET("users/{id}")
suspend fun getUser(@Path("id") id: String): User
}
// 呼び出し側
val user = apiService.getUser("123")
Retrofitはインターフェースを「型」として定義するので可読性が高く、また記述が楽なのもメリットの1つです。
"インターフェースを「型」として定義する"とは?
インターフェースを「型」として定義すると、例えば上述のコードからは以下のことが分かるようになります。
- 戻り値がUser型である
- getUser()の引数(id)にはString型を入れなければならない
このように、引数や戻り値に明確な型を指定してあげることで、ビルド前にエラーに気付くことができるようになり、堅牢性が高まります。
Ktorについて
Ktorは、JetBrains社が開発しているフレームワークで、近年使われるようになってきたものになります。Ktorの特徴は、KMP(Kotlin Multiplatform)に対応している点と、DSL(ドメイン固有言語)ベースで書くという点です。Retrofitと同様に、「ユーザー情報を取得する」処理をKtorで記述してみると以下のようになります。
val client = HttpClient(OkHttp) {
install(ContentNegotiation) {
json() // シリアライズの設定
}
}
// 呼び出し処理
val user: User = client.get("https://api.example.com/users/123").body()
Ktorでは、HttpClient(OkHttp) {}の中で様々なカスタマイズを行うことができます。例ではシリアライズの設定のみでしたが、他にもタイムアウトの設定や、共通リクエストの設定なども行うことができます。このように、Ktorは柔軟性と拡張性が高いことが大きなメリットです。
DSL(ドメイン固有言語)で書くメリットは?
DSL形式で記述することで、リクエストごとの細かいカスタマイズが直感的に行うことができます。 例えば、「このリクエストだけ特定のヘッダーを追加したい」や「動的にURLパラメータを変化させたい」といった場合に、インターフェースを変更することなく、呼び出し元のコードブロック内で完結して記述できるため、複雑な通信要件に対応しやすくなります。
両者の違いのまとめ
| 特徴 | Retrofit | Ktor |
|---|---|---|
| 開発元 | Square | JetBrains |
| 記述スタイル |
アノテーションベース ( @GET, @Bodyなど) |
DSLベース (コードブロックで記述) |
| アプローチ |
静的 (事前にインターフェースで型を定義) |
動的 (処理の中でリクエストを組み立て) |
| プラットフォーム | 主にAndroid / JVM |
KMP (Kotlin Multiplatform) (iOS, Web等とコード共有が可能) |
| 最大のメリット | 定義が一覧化され、可読性と堅牢性が高い | 構成の自由度が高く、柔軟性と拡張性が高い |
ではどう使い分ければ良いのか
それぞれの特徴を紹介してきましたが、使い分けの基準自体は単純で、「プロジェクトにKMPを導入するつもりである(または将来的に導入する見込みがある)」かどうかだと思います。KMPを導入予定であればKtor、そうでなければ学習コストの低いRetrofitを使うのが吉です。
おわりに
個人的にはRetrofitの方が好みで、インターンの面接でRetrofitを選んだ理由について「Ktorに比べて何をやっているのか分かりやすいからです!」と答えていたほどなのですが、今後はKtorの需要が高まっていきそうなので、次やるプロジェクトではKtorを使ってみる予定です。