はじめに
Android開発でAPI通信をするなら、ほとんどの人が使っているであろうRetrofitとOkHttp。
ただ「とりあえず動く」レベルで書いていると、タイムアウトや再試行、ログ管理あたりで後々つまづきやすいです。
今回は、Retrofit+OkHttpを組み合わせて、安定して通信できるようにするための基本構成を紹介します。
依存関係を追加する
implementation "com.squareup.retrofit2:retrofit:2.11.0"
implementation "com.squareup.retrofit2:converter-gson:2.11.0"
implementation "com.squareup.okhttp3:okhttp:4.12.0"
implementation "com.squareup.okhttp3:logging-interceptor:4.12.0"
Retrofitの最新安定版は2.11系、OkHttpは4.12系で、Android 14〜16でも安定動作しています。
ログ出力のためにlogging-interceptor
も追加しておくと便利です。
OkHttpClientの基本設定
まずはOkHttpのインスタンスを安全に構成します。
object ApiClient {
private val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
private val client = OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.addInterceptor(loggingInterceptor)
.retryOnConnectionFailure(true)
.build()
private val retrofit = Retrofit.Builder()
.baseUrl("https://api.example.com/")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
val service: ApiService = retrofit.create(ApiService::class.java)
}
ここでのポイントは以下の4つです。
connectTimeout
/readTimeout
/writeTimeout
を明示的に指定retryOnConnectionFailure(true)
で再試行を有効化HttpLoggingInterceptor
で通信ログを出力OkHttpClient
をobject
で1つにまとめてシングルトン化
これでアプリ全体から安全に共通のHTTPクライアントを利用できます。
APIインターフェースを定義
interface ApiService {
@GET("users")
suspend fun getUsers(): Response<List<User>>
@POST("login")
suspend fun login(@Body request: LoginRequest): Response<LoginResponse>
}
Retrofitでは、HTTPメソッドごとにアノテーションで指定するだけ。
Kotlin Coroutines対応なので、suspend
関数で書くのが今の主流です。
API呼び出しの実装例
viewModelScope.launch {
try {
val response = ApiClient.service.getUsers()
if (response.isSuccessful) {
val users = response.body()
Log.d("API", "ユーザー取得成功: ${users?.size}件")
} else {
Log.e("API", "エラー: ${response.code()}")
}
} catch (e: IOException) {
Log.e("API", "ネットワークエラー: ${e.message}")
} catch (e: HttpException) {
Log.e("API", "HTTPエラー: ${e.code()}")
}
}
通信は基本的にtry-catchで包んでおくのが鉄則です。
サーバーエラーやタイムアウトが起きても、アプリを落とさずに済みます。
よくある失敗パターン
① Contextを直接使ってしまう
ViewModelやRepositoryの中でContextを直接参照するのは危険です。
RetrofitはContextに依存しない設計にしておくのがベターです。
② OkHttpClientを毎回生成している
Retrofit.Builder()
やOkHttpClient.Builder()
を都度生成していると、無駄なスレッドやメモリを消費します。
シングルトンパターンで1回だけ作るようにしましょう。
③ タイムアウトが長すぎる/短すぎる
APIの性質に合わせて調整することが重要です。
5〜10秒以内にレスポンスがないなら、再試行させたほうがUX的にも良いことが多いです。
OS16対応ポイント
Android 16ではネットワークアクセス制限が一部強化され、
HTTP/3(QUIC)対応サーバーへの接続でタイムアウト検知の挙動が変わります。
Retrofit 2.11+OkHttp 4.12以降では自動的に対応しているので、
特別な実装変更は不要です。
ただし、古いライブラリを使っている場合はログが出なくなることもあるため、HttpLoggingInterceptor
の更新は忘れずに行いましょう。
まとめ
- OkHttpClientはシングルトンで管理
- ログ出力とタイムアウト設定を明示する
- 例外処理(IOException / HttpException)でクラッシュ防止
- Android 16でも安定動作する最新バージョンを利用
Retrofit+OkHttpは非常に強力ですが、
設定を一歩間違えると「動くけど不安定」になりがちです。
基本の設定を固めておくと、後から機能を追加しても壊れにくくなるのでおすすめです。
コメント