Java Android改型参数化@Headers

Java Android改型参数化@Headers,java,android,annotations,retrofit,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")

我正在使用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
)
@GET(“/users”)
无效getUsers(
@标题(“授权”)字符串身份验证,
@标题(“X-Api-Version”)字符串版本,
回调
)

是的,您可以在运行时传递它们。事实上,和你打出来的差不多。这将在API接口类中,名为saySecretApiInterface.java

public interface SecretApiInterface {

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

}
然后,您将请求中的参数传递到此接口,大致如下:(该文件将是例如SecretThingRequest.java

public类SecretThingRequest扩展了该请求{
私有字符串令牌;
公共加密请求(字符串令牌){
super(SecretThing.List.class、SecretApiInterface.class);
this.token=token;
}
@凌驾
public SecretThing.List loadDataFromNetwork(){
secretapipinterface service=getService();
return service.getSecretThings(莫名其妙地.Magically.getToken());
}
}
其中
以某种方式.Magically.getToken()
是一个返回令牌的方法调用,它取决于您在何处以及如何定义它

当然,在接口实现中可以有多个
@Header(“Blah”)字符串Blah
注释,就像您的例子一样

我发现它也让人困惑,清楚地说它取代了标题,但它没有
事实上,它是与
@头一起添加的(“硬编码字符串”的使用”)
注释


希望这有帮助;)

除了使用@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());
            }                    
        }
    });
p/s:如果您使用的是Reformation2,您应该使用
拦截器
而不是
请求拦截器


由于
RequestInterceptor
在改型2.0中不再可用

,因此公认的答案是旧版本的改型。对于未来的观众,使用
改造
2.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();
希望它能帮助别人。:)

改装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();

我正在使用它连接到GitHub。

你知道这一点吗?我需要在标题中传递一个令牌,我也在寻找解决方案,从文档中可以看出,方法上的注释将字段逐个添加到标题中,但只支持文本。参数注释将标题替换为提供的值。此处相同,在使用改型时无法找到如何处理会话。我们不需要传递所有项,改型本身处理所有项。请在StackOverflow中检查我的答案。这没有直接关系,但如果您发现需要从请求对象获取值以生成授权标头,则需要扩展ApacheClient并重复执行请求对象(列表标头=…;请求requestNew=新请求(request.getMethod(),request.getUrl(),headers,request.getBody();request=requestNew)。这是一个弄乱编码的技巧,最好使用@nana的答案
RestAdapter
取决于改型1,在改型2中是
改型
。我将使用Refught2,所以如果像上面的代码那样使用
RequestInterceptor
,就不会有问题了?我在文档中发现它不会替换现有的头:“注意,头不会相互覆盖。”检查和“头操纵”在dagger2的常见用法中,Refught2将是单例的,因此不会每次都创建httpclient。在这种情况下,isUserLoggedIn()没有意义,对吗?目前我能看到的唯一解决方案是,当用户登录状态更改时,强制重新初始化Reformation2,以便在请求中添加或删除相应的头。。还是有一些我目前看不到的显而易见的解决方案?谢谢。@bajicdusko这是我完全一样的connundrum。你找到解决办法了吗?以前的版本效率更高,这似乎太浪费了,也很奇怪。@deed02392您可以设置一个复合的
拦截器
,您可以在以后的阶段设置或重置拦截器。然而,我认为作为一个单身者进行改造可能是早期优化的标志。创建一个新的改造实例并没有任何开销:我并没有真正深入地考虑它。我有一些ApiFactory类,它也是用dagger2初始化的,它负责更新的初始化。我在ApiFactory中公开了一个公共方法,它在需要时强制重新初始化改造实例,所以它非常简单。我可能做错了,但它完成了任务,我只将其用于授权标题,以便在用户登录或注销时使用。另一个选择是在端点定义中使用@Header注释,这对我来说是不可接受的。我应该在每个端点上设置它,这是不实际的。@pablisco啊,据我所知,一旦创建了一个实例,就不能添加或删除
拦截器。
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();