Android 改造参数化@Header

我正在使用 OAuth,并且每次发出请求时都需要将 OAuth 令牌放在头部。我看到了 @Header注释,但是有没有办法让它参数化,这样我就可以在运行时传入?

概念是这样的

@Header({Authorization:'OAuth {var}', api_version={var} })

你能在运行时传递它们吗?

@GET("/users")
void getUsers(
@Header("Authorization") String auth,
@Header("X-Api-Version") String version,
Callback<User> callback
)
86017 次浏览

Yes, you can pass them in runtime. As a matter of fact, pretty much exactly as you typed it out. This would be in your API interface class, named say SecretApiInterface.java

public interface SecretApiInterface {


@GET("/secret_things")
SecretThing.List getSecretThings(@Header("Authorization") String token)


}

Then you pass the parameters to this interface from your request, something along those lines: (this file would be for example SecretThingRequest.java)

public class SecretThingRequest extends RetrofitSpiceRequest<SecretThing.List, SecretApiInteface>{


private String token;


public SecretThingRequest(String token) {
super(SecretThing.List.class, SecretApiInterface.class);
this.token = token;
}


@Override
public SecretThing.List loadDataFromNetwork() {
SecretApiInterface service = getService();
return service.getSecretThings(Somehow.Magically.getToken());
}
}

Where Somehow.Magically.getToken() is a method call that returns a token, it is up to you where and how you define it.

You can of course have more than one @Header("Blah") String blah annotations in the interface implementation, as in your case!

I found it confusing too, the documentation clearly says it replaces the header, but it DOESN'T!
It is in fact added as with @Headers("hardcoded_string_of_liited_use") annotation

Hope this helps ;)

Besides using @Header parameter, I'd rather use RequestInterceptor to update all your request without changing your interface. Using something like:

RestAdapter.Builder builder = new RestAdapter.Builder()
.setRequestInterceptor(new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
request.addHeader("Accept", "application/json;versions=1");
if (isUserLoggedIn()) {
request.addHeader("Authorization", getToken());
}
}
});

p/s : If you are using Retrofit2, you should use Interceptor instead of RequestInterceptor

Since RequestInterceptor is not longer available in Retrofit 2.0

The accepted answer is for an older version of Retrofit. For future viewers the way to do this with Retrofit 2.0 is using a custom OkHttp client:

OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Builder ongoing = chain.request().newBuilder();
ongoing.addHeader("Accept", "application/json;versions=1");
if (isUserLoggedIn()) {
ongoing.addHeader("Authorization", getToken());
}
return chain.proceed(ongoing.build());
}
})
.build();


Retrofit retrofit = new Retrofit.Builder()
// ... extra config
.client(httpClient)
.build();

Hope it helps someone. :)

Retrofit 2.3.0

OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder
.addInterceptor(new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request.Builder newRequest = request.newBuilder().header("Authorization", accessToken);
return chain.proceed(newRequest.build());
}
});


Retrofit retrofit = new Retrofit.Builder()
.baseUrl(GithubService.BASE_URL)
.client(okHttpClientBuilder.build())
.addConverterFactory(GsonConverterFactory.create())
.build();

I am using this to connect to GitHub.