Retrofitでカスタムアノテーションを使う
Updated at Sat, Nov 24, 2018Retrofit 2.5.0からカスタムアノテーションが使えるようになったので、それの紹介です。
例をあげて説明します。特定のリクエストのヘッダーに認証情報を付与したいとします。
まず最初にアノテーションを定義します。
annotation class RequireAuth
次に、上記で定義したアノテーションを使い、Apiを定義します。
interface ApiService {
@RequireAuth
@GET("login")
fun login(: retrofit2.Call<Unit>
}
次に、RequireAuth
を処理するためのokhttp3.Interceptor
を定義します。
class AuthInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
val invocation = request.tag(Invocation::class.java)
val authAnnotation = invocation?.method()?.getAnnotation(RequireAuth::class.java)
if (authAnnotation != null) {
request = request
.newBuilder()
.addHeader("Authorization", "Basic AAAAA").build()
}
return chain.proceed(request)
}
}
ここでのポイントは、val invocation = request.tag(Invocation::class.java)
です。
Retrofit 2.5.0からInvocation
が追加され、Request
からInvocation
が取得できるようになりました。
Invocation
には、処理しているRequest
のjava.lang.reflect.Method
が格納されており、
そこからアノテーションの情報を取得することができます。
val authAnnotation = invocation?.method()?.getAnnotation(RequireAuth::class.java)
で、
メソッドにRequireAuth
アノテーションが付与されているかどうかを知ることが出来ます。
RequireAuth
アノテーションがついていれば、Request
のヘッダーに認証情報を追加します。
最後に、上記のInterceptor
をOkHttpクライアントに付与します。
val client = OkHttpClient.Builder()
.addInterceptor(AuthInterceptor())
.build()
これでRetrofitでカスタムアノテーションを使うことが出来ます!!
Invocation以前の場合
Invocation以前は、Headers
を使い認証情報を付与するテクニックがありました。
詳しくはMaking Retrofit Work For Youにあります。
@Headers("Auth: true")
@GET("useheaderlogin")
fun login(): retrofit2.Call<Unit>
class Auth2Interceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
var request = chain.request()
if (request.header("Auth") != null) {
request = request
.newBuilder()
.addHeader("Authorization", "Basic BBBBB").build()
}
return chain.proceed(request)
}
}
このコードでも動くのですが、カスタムアノテーションを定義するやり方のほうが意味が伝わりやすいと思うので、よりよいと思います。
まとめ
- Retrofit 2.5.0でInvocationが追加されてカスタムアノテーションが使えるようになりました
- さらにInvocationはメソッドの引数リストを持っており、ログやアナリティクスなどに有効に使うことができます
今回の検証に用いたサンプルコードはここにあります😃