AndroidでAPI通信をするなら定番のライブラリがRetrofitですよね。使いやすくて便利なんですが、デフォルトのまま使っていると「タイムアウト周りどうなってるの?」って気になることがあると思います。特に通信環境が不安定な場所だと、いつまでも待たされてユーザー体験が悪くなってしまいます。
今回はRetrofit+OkHttpで、リクエストのタイムアウトを設定する方法をまとめてみました。
Retrofit単体ではタイムアウトは設定できない
まず押さえておきたいのは、Retrofit自体にはタイムアウトの設定項目がないという点です。RetrofitはHTTPクライアントとしてOkHttpを内部的に使っているので、実際にタイムアウトを制御するのはOkHttpの役割になります。
つまり「Retrofitでタイムアウトを設定したい」と思ったら、OkHttpClient
をカスタマイズしてRetrofitに渡すのが正しいやり方です。
OkHttpClientのタイムアウト設定
OkHttpでは以下の3種類のタイムアウトが用意されています。
- connectTimeout:サーバーに接続するまでの時間
- readTimeout:サーバーからデータを読み込むまでの時間
- writeTimeout:サーバーにデータを書き込むまでの時間
デフォルトはすべて10秒ですが、アプリの要件によって変更した方がいいことも多いです。
実装例(Kotlin)
val okHttpClient = OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.writeTimeout(20, TimeUnit.SECONDS)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("https://api.example.com/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
上の例では接続は15秒、読み書きは20秒にしています。状況によってはもっと短くしてもいいですし、逆にAPIの処理が重いなら長めに取るのもアリですね。
どのくらいの値にすればいいの?
「タイムアウトの秒数ってどれくらいが正解?」と思う方も多いはずです。これはアプリの用途やユーザーが使う環境によっても変わります。
- ニュースアプリやSNSのようにサクサク動いてほしい場合 → 短め(5〜10秒程度)
- 大きなファイルをアップロード・ダウンロードする場合 → 長め(30秒〜数分)
- 社内システムなど安定したネットワーク前提の場合 → デフォルトでも十分
ポイントは「失敗をすぐに検知してユーザーに再試行させるか」「多少待ってでも成功を優先するか」です。UXの設計に合わせて決めると良いですね。
エラーハンドリングもセットで考える
タイムアウトを設定したら、それに合わせてエラーハンドリングも忘れずに入れておきましょう。タイムアウトが発生するとSocketTimeoutException
が投げられます。これをキャッチして「通信に時間がかかっています。再試行してください」といったメッセージを出せば、ユーザーにとってもわかりやすいです。
try {
val response = api.getData()
if (response.isSuccessful) {
// 成功時の処理
} else {
// サーバーエラー時の処理
}
} catch (e: SocketTimeoutException) {
// タイムアウト時の処理
showToast("通信がタイムアウトしました。再試行してください。")
}
例外の種類をしっかり分けてハンドリングすると、単なる「エラー」よりも親切な挙動になりますね。
まとめ
- Retrofit自体にはタイムアウト設定はなく、OkHttpで制御する
- connectTimeout / readTimeout / writeTimeout を用途に応じて調整できる
- タイムアウト値はアプリの性質とUXに合わせて決めるのがポイント
- 例外処理と組み合わせて「わかりやすいエラーメッセージ」を出すとユーザーに優しい
Retrofitを使うと通信処理自体はとてもシンプルに書けますが、細かい挙動をコントロールするにはOkHttpの設定が欠かせません。タイムアウトの調整はアプリの使い勝手に直結する部分なので、ぜひ見直してみてください。
コメント