Android Retrofit参数化@Headers

jpo*_*s18 81 java android annotations retrofit

我正在使用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
)
Run Code Online (Sandbox Code Playgroud)

小智 95

除了使用@Header参数之外,我宁愿使用RequestInterceptor更新您的所有请求而不更改您的界面.使用类似的东西:

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());
            }                    
        }
    });
Run Code Online (Sandbox Code Playgroud)

p/s:如果您使用的是Retrofit2,您应该注意到Interceptor而不是RequestInterceptor

由于RequestInterceptor在Retrofit 2.0中不再可用

  • 这不是直接相关的,但是如果您发现自己需要从请求对象获取值以生成Authorization标头,则需要扩展ApacheClient并在执行副本中使用Request对象(List <Header> headers = ... ;请求requestNew = new Request(request.getMethod(),request.getUrl(),headers,request.getBody()); request = requestNew). (3认同)

nan*_*ana 52

是的,您可以在运行时传递它们.事实上,几乎就像你输入它一样.这将在您的API接口类中,名为SecretApiInterface.java

public interface SecretApiInterface {

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

}
Run Code Online (Sandbox Code Playgroud)

然后你从你的请求中将参数传递给这个接口,类似于这些:(这个文件将是例如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());
    }
}
Run Code Online (Sandbox Code Playgroud)

哪里Somehow.Magically.getToken()是返回一个令牌的方法调用,它是由你在何处以及如何定义它.

您当然可以@Header("Blah") String blah在接口实现中使用多个注释,就像您的情况一样!

我发现它也令人困惑,文档清楚地说它取代了标题,但它没有!
它实际上与@Headers("hardcoded_string_of_liited_use")注释一样添加

希望这可以帮助 ;)


pab*_*sco 35

接受的答案是旧版本的Retrofit.对于未来的观众来说,使用Retrofit2.0的方法是使用自定义的OkHttp客户端:

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();
Run Code Online (Sandbox Code Playgroud)

希望它可以帮助某人.:)

  • 与dagger2一样,retrofit2将是singleton,因此每次都不会创建httpclient.在那种情况下isUserLoggedIn()没有意义,我是对的吗?目前我只能看到的解决方案是在用户登录状态发生变化时强制改造重新初始化,以便在请求中添加或删除相应的标题..或者有一些我目前无法看到的明显解决方案?谢谢. (5认同)
  • @bajicdusko这是我完全相同的connundrum.你找到了解决方案吗?看起来很浪费,而且之前的版本效率更高. (2认同)

Soo*_*tos 5

改造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();
Run Code Online (Sandbox Code Playgroud)

我正在使用它来连接到GitHub。