Android Retrofit Parametreli @Headers


85

OAuth kullanıyorum ve her istekte bulunduğumda başlığıma OAuth jetonunu koymam gerekiyor. @HeaderEk açıklamayı görüyorum , ancak çalışma zamanında geçebilmem için onu parametreli hale getirmenin bir yolu var mı?

İşte konsept

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

Bunları Runtime'da iletebilir misin?

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

Bunu hiç çözdün mü?
Başlıkta

Ayrıca buna bir çözüm arıyorum, dokümantasyondan , yöntemdeki @Headers () ek açıklamasının başlıklara alanları birer birer eklediği gibi görünüyor , ancak yalnızca değişmez değerleri destekliyor. Ve @Header ( "parametresi") dize dize parametresi açıklama değiştirir sağlanan değerle başlığını.
nana

2
Aynı burada, güçlendirme kullanılırken oturumların nasıl ele alınacağını bulamadık.
CUM

Tüm öğeleri geçmemize gerek yoktu, iyileştirme kendi başına hepsini hallediyor. Lütfen StackOverflow'daki yanıt bağlantımı kontrol edin .
Subin Babu

Yanıtlar:


98

@Header parametresini kullanmanın yanı sıra, tüm isteğinizi arayüzünüzü değiştirmeden güncellemek için RequestInterceptor'ı kullanmayı tercih ederim. Şunun gibi bir şey kullanarak:

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: Retrofit2 kullanıyorsanız, Interceptorbunun yerine kullanmalısınızRequestInterceptor

Yana RequestInterceptorRecommended 2.0 kullanılamaz artık


3
Bu doğrudan ilgili değildir, ancak Yetkilendirme başlığınızı oluşturmak için istek nesnesinden değerler almanız gerektiğini fark ederseniz, ApacheClient'i genişletmeniz ve İstek nesnesini çoğaltmanız gerekir (List <Header> başlıkları = ... ; Request requestNew = new Request (request.getMethod (), request.getUrl (), headers, request.getBody ()); request = requestNew).

1
Bu kodlanmış bir hileyi karıştıran bir numara, @
nana'nın

1
RestAdapterRetrofit1'e bağlıdır, Retrofit2'de budur Retrofit. Retrofit2'yi kullanacağım, bu nedenle RequestInterceptoryukarıdaki kod gibi kullanılırsa sorun olmaz mı?
Huy Tower

55

Evet, bunları çalışma zamanında geçirebilirsiniz. Aslında, hemen hemen yazdığınız gibi. Bu, say SecretApiInterface.java adlı API arayüz sınıfınızda olacaktır.

public interface SecretApiInterface {

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

}

Ardından parametreleri bu arayüze isteğinizden iletirsiniz, bu satırlar boyunca bir şey: (bu dosya örneğin SecretThingRequest.java olabilir )

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());
    }
}

Somehow.Magically.getToken()Bir belirteci döndüren bir yöntem çağrısı nerede , onu nerede ve nasıl tanımlayacağınız size bağlıdır.

Elbette @Header("Blah") String blah, sizin durumunuzda olduğu gibi, arayüz uygulamasında birden fazla nota sahip olabilirsiniz !

Ben de kafa karıştırıcı buldum , dokümantasyon açıkça başlığın yerini aldığını söylüyor , ama YAPILMIYOR !
Aslında @Headers("hardcoded_string_of_liited_use")ek açıklamada olduğu gibi eklenir

Bu yardımcı olur umarım ;)


1
Dokümanlarda, mevcut bir başlığın yerini almadığını buldum: "Başlıkların birbirlerinin üzerine yazmadığını unutmayın." Square.github.io/retrofit ve "Header Manipulation" ı kontrol edin
Amio.io

37

Kabul edilen yanıt, Retrofit'in eski bir sürümü içindir. Gelecekteki izleyiciler için bunu Retrofit2.0 ile yapmanın yolu özel bir OkHttp istemcisi kullanmaktır:

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

Umarım birine yardımcı olur. :)


5
Dagger2 ile ortak kullanımda, retrofit2 tekil olacaktır, bu nedenle her seferinde httpclient oluşturulmayacaktır. bu durumda isUserLoggedIn () mantıklı değil, değil mi? Şu anda görebildiğim tek çözüm, kullanıcı oturum açma durumu değiştiğinde retrofit2 yeniden başlatmaya zorlamaktır, böylece uygun başlık istekten eklenir veya kaldırılır .. veya şu anda göremediğim bariz bir çözüm var mı? Teşekkürler.
bajicdusko

2
@bajicdusko bu benim tam olarak aynı bağlantım. Bir çözüm buldun mu? Önceki sürümün daha verimli olması o kadar savurgan ve garip görünüyor.
deed02392

@ deed02392 Önleyiciyi Interceptordaha sonraki bir aşamada ayarlayabileceğiniz veya sıfırlayabileceğiniz bir bileşik ayarlayabilirsiniz. Bununla birlikte, tekli olarak güçlendirmenin erken bir optimizasyon işareti olabileceğini iddia ediyorum. Yeni bir retrofit örneği oluşturmanın ek yükü yoktur: github.com/square/retrofit/blob/master/retrofit/src/main/java/…
pablisco

Bunu gerçekten derinlemesine düşünmedim. Ayrıca dagger2 ile başlatılan bazı ApiFactory sınıfım var ve güçlendirmenin başlatılmasından sorumlu. ApiFactory'de, gerektiğinde retrofit örneğinin yeniden başlatılmasını zorlayan bir genel yöntemi açığa çıkardım, bu yüzden oldukça basit. Yanlış yapabilirim, ancak işi yaptı ve onu yalnızca Yetkilendirme başlığı için kullanıyorum, bu nedenle kullanıcı oturum açarken veya oturumu kapatırken kullanılır. Başka bir seçenek de uç nokta tanımının içinde @Header ek açıklamasını kullanmaktır ki bu benim için kabul edilemez. Bunu pratik olmayan her uç noktaya ayarlamalıyım.
bajicdusko

@pablisco Ah, anladığım kadarıyla Interceptorbir Retrofit2 örneği oluşturduktan sonra s ekleyemez veya kaldıramazsınız .
deed02392

7

Güçlendirme 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'a bağlanmak için bunu kullanıyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.