android-retrofit について
コルーチン、kotlinx.serialization、Hiltを使うAndroid開発者向けのRetrofitネットワーキングスキルです。エンドポイントの戻り値、認証方針、ネットワークエラーとDTOをrepository境界内に保つ方法を扱います。
主な機能
- 01Suspendエンドポイント設計
- 02本文とResponseの使い分け
- 03OkHttpとJSONの設定
- 04Interceptorによるトークン認証
- 05repository層でのエラー変換
活用シーン
- 01Retrofitサービスメソッドの定義
- 02認証トークン不在時の動作選択
- 03柔軟なAPI向けJSON処理の設定
- 04通信エラーをViewModelに渡さない設計
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ rcosteira79/ android-skills --skill android-retrofitインストール後、Claude Code で/android-retrofitを入力して読み込まれたか確認します。
詳細
Retrofit を使用した Android のネットワーク通信
コルーチン、kotlinx.serialization、Hilt を使用した、Android 向けの最新の Retrofit セットアップです。このリファレンスでは、サービスインターフェース、Hilt モジュールの配線、コンバーターのセットアップといった標準的な定型コードではなく、間違えやすい判断について説明します。
サービスインターフェース
すべてのエンドポイントを suspend 関数として宣言します。ボディの型を直接返してください。2xx 以外の場合、Retrofit は HttpException をスローするため、リポジトリの境界でシンプルに try/catch できます。ステータスコード、ヘッダー、またはエラーボディ(サーバー側のバリデーションメッセージなど)が必要な場合に限り、Response<T> を使用します。
// Direct body — throws HttpException on non-2xx; the common case
@GET("users/{user}/repos")
suspend fun listRepos(@Path("user") user: String): List<Repo>
// Response wrapper — only when you need code/headers/error body
@GET("users/{user}")
suspend fun getUser(@Path("user") user: String): Response<User>
「念のため」とすべてのエンドポイントを Response<T> でラップすると、ボディだけが必要な場合でも、呼び出し側で isSuccessful を確認し、nullable なボディを処理する必要が生じます。これは避けてください。
OkHttp と JSON
標準的な配線(Hilt の @Module/@Provides @Singleton 内)では、レベルを BuildConfig.DEBUG に応じて切り替える HttpLoggingInterceptor、適切な接続/読み取りタイムアウト、および kotlinx.serialization コンバーター(json.asConverterFactory("application/json".toMediaType()))を使用します。ペイロードの形式が厳密でない API では、次のように設定します。
Json { ignoreUnknownKeys = true; coerceInputValues = true; isLenient = true }
認証:インターセプターと throw するか proceed するかの判断
エンドポイントごとの @Header ではなく、Interceptor を使ってトークンを付与します。@Header パラメーターをひとつ付け忘れるだけで、コンパイル時ではなく実行時に未認証のリクエストとして失敗するためです。最も間違えやすいのは、トークンがない場合にどうするかです。
class AuthInterceptor @Inject constructor(
private val tokenProvider: TokenProvider,
) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val token = tokenProvider.getToken()
?: throw IOException("Auth token unavailable") // fail fast — see note below
val request = chain.request().newBuilder()
.header("Authorization", "Bearer $token")
.build()
return chain.proceed(request)
}
}
throw するか proceed するか:すべてのエンドポイントで認証が必要な場合は、throw してください。トークンがないことをすぐに表面化させれば、原因の分かりにくい 401 がひそかに発生するのを防げます。同じ
OkHttpClientを認証が必要なエンドポイントと公開エンドポイントで共有する場合に限り、ヘッダーを付けずに続行します:?: return chain.proceed(chain.request())。すべての呼び出しで認証が必要なのに、何も言わずに続行するのはよくある間違いです。
エラー処理
エラー境界はリポジトリです。そこで HttpException/IOException を捕捉し、ドメインエラー型にマッピングしてください。Retrofit/OkHttp の例外型を ViewModel に渡してはいけません。また、Retrofit の DTO を ViewModel に公開してはいけません。ここでエラー階層を再定義しないでください。リポジトリのパターンと共有の DataError 分類については、android-skills:android-data-layer を参照してください。
チェックリスト
- すべてのサービス関数が
suspendである -
Response<T>は、ステータスコード、ヘッダー、またはエラーボディが必要な場合に限って使用している -
OkHttpClientのログ出力がBuildConfig.DEBUGによって制御されている。適切なタイムアウトが設定されている -
Interceptorを使って認証を適用している。トークンがない場合の方針(throw するか proceed するか)を選択している - ネットワーク例外をリポジトリでドメイン型にマッピングしている。DTO が ViewModel に渡らない