从 Retrofit 2.0 开始,您有两个选择
1) 使用 OkHttp 2.2+ 使用Interceptor
在 Http 级别,您可以更好地控制请求,因此您可以执行一些操作,例如仅将标头应用于对特定端点发出的特定请求,等等。
public class MyOkHttpInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
if (!"/posts".contains(originalRequest.url()) ) {
return chain.proceed(originalRequest);
}
String token = // get token logic
Request newRequest = originalRequest.newBuilder()
.header("X-Authorization", token)
.build();
return chain.proceed(newRequest);
}
[...]
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.networkInterceptors().add(new MyOkHttpInterceptor());
OkClient okClient = new OkClient(okHttpClient);
YourApi api = new RestAdapter.Builder()
.setEndpoint(url)
.setClient(okClient)
.build()
.create(YourApi.class);
编辑:
添加@JakeWarthon 注释作为另一个选项也是有效的。
2) 将@Header 放在方法参数上,并在调用时将其作为值传递。
来自docs:
// Replaces the header with the the value of its target.
@GET("/")
void foo(@Header("Accept-Language") String lang, Callback<Response> cb);
标头参数可能为空,这将在请求中忽略它们。传递列表或数组将为每个非空项生成一个标头。
注意:标题不会相互覆盖。所有具有相同名称的标头都将包含在请求中。
编辑:此选项不应被视为 Retrofit 2.* 放弃了对拦截器的支持。
3) 用户改造 RequestInterceptor
来自文档:
在执行之前拦截每个请求以添加额外数据。
你可以做类似的事情
public class MyRetrofitInterceptor implements RequestInterceptor {
@Override
public void intercept(RequestFacade req) {
String token = // get token logic
if (token != null) {
req.addHeader("X-Authorization", token);
}
}
[...]
YourApi api = new RestAdapter.Builder()
.setEndpoint(url)
.setRequestInterceptor(new MyRetrofitInterceptor())
.build()
.create(YourApi.class);
这种方法的“问题”是拦截器将在所有端点上执行,因为它是在 RestAdapter 级别设置的,而不是每个端点。此外,RequestFacade 没有公开太多有关请求的信息,因此没有机会在其周围添加太多逻辑。