Retrofit 2.0'da Başlıklar eklemek için durdurucu nasıl kullanılır?


96

Ekibimiz Retrofit 2.0'ı benimsemeye karar verdi ve ben bununla ilgili bazı ilk araştırmalar yapıyorum. Bu kütüphanede acemiyim.

Android uygulamamızda Retrofits 2.0interceptor aracılığıyla özelleştirilmiş başlıklar eklemek için nasıl kullanılacağını merak ediyorum . Retrofit 1.X'te başlık eklemek için kullanma hakkında birçok öğretici var , ancak API'ler en son sürümde çok değiştiği için, bu yöntemleri yeni sürümde nasıl uyarlayacağımı bilmiyorum. Ayrıca Retrofit, yeni belgelerini henüz güncellemedi.interceptor

Örneğin, aşağıdaki kodlarda, Interceptorfazladan üstbilgi eklemek için sınıfı nasıl uygulamalıyım ? Ayrıca, belgelenmemiş Chainnesne tam olarak nedir? Ne zaman intercept()aranacak?

    OkHttpClient client = new OkHttpClient();
    client.interceptors().add(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Response response = chain.proceed(chain.request());

            // How to add extra headers?

            return response;
        }
    });

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_API_URL)
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

1
BASE_API_URL'nizin ile bittiğinden /ve API URL'lerinizin ( stuff/post/whatever) olmadığından emin olun
EpicPandaForce

Yanıtlar:


120

Şuna bak.

public class HeaderInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request()
                .newBuilder()
                .addHeader("appid", "hello")
                .addHeader("deviceplatform", "android")
                .removeHeader("User-Agent")
                .addHeader("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0")
                .build();
        Response response = chain.proceed(request);
        return response;
    }
}

Kotlin

class HeaderInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response = chain.run {
        proceed(
            request()
                .newBuilder()
                .addHeader("appid", "hello")
                .addHeader("deviceplatform", "android")
                .removeHeader("User-Agent")
                .addHeader("User-Agent", "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0")
                .build()
        )        
    }
}

Teşekkürler!! Yani, intercept()uygulamadan her istek gönderildiğinde bu tetikleniyor? Yönlendirme için ara yanıtı yakalayabilir miyiz, yoksa sadece son yanıtı alabilir miyiz?
hackjutsu

Bu her istek için çağrılır ve doğru biliyorsam, bunun nedeni onu bir ağ engelleyicisi olarak değil, bir engelleyici olarak eklemenizdir. Sanırım burada yalnızca son yanıtı alabileceksiniz, ancak yönlendirmeleri kafamın tepesinden bilmediğim yönlendirmeler olarak görmeye izin veren bir yapılandırma olabilir (http URL bağlantısı için de bir tane var.)
EpicPandaForce,

1
Sadece şu bağlantıya bakın: github.com/square/okhttp/wiki/Interceptors ve ihtiyacım olan bilgileri alın :) Teşekkür ederim ~
hackjutsu

5
Fyi, bunun yerine bir inşaatçı kullanmanız gerekiyor client.interceptors(). Bu, new OkHttpClient.Builder().addInterceptor(<Your Interceptor>).build()
01'de

22

Kabul edilen cevaptan başka bir alternatif

public class HeaderInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();

        request = request.newBuilder()
                .addHeader("headerKey0", "HeaderVal0")
                .addHeader("headerKey0", "HeaderVal0--NotReplaced/NorUpdated") //new header added
                .build();

        //alternative
        Headers moreHeaders = request.headers().newBuilder()
                .add("headerKey1", "HeaderVal1")
                .add("headerKey2", "HeaderVal2")
                .set("headerKey2", "HeaderVal2--UpdatedHere") // existing header UPDATED if available, else added.
                .add("headerKey3", "HeaderKey3")
                .add("headerLine4 : headerLine4Val") //line with `:`, spaces doesn't matter.
                .removeAll("headerKey3") //Oops, remove this.
                .build();

        request = request.newBuilder().headers(moreHeaders).build();

        /* ##### List of headers ##### */
        // headerKey0: HeaderVal0
        // headerKey0: HeaderVal0--NotReplaced/NorUpdated
        // headerKey1: HeaderVal1
        // headerKey2: HeaderVal2--UpdatedHere
        // headerLine4: headerLine4Val

        Response response = chain.proceed(request);
        return response;
    }
}

Güzel! Yani request.newBuilder().headers(moreHeaders).build()orijinal başlıkları koruyacak mı?
hackjutsu

1
Evet. RemoveAll (Dize adı) çağrılmadıkça istekten hiçbir üstbilgi kaldırılmaz .
VenomVendor

@VenomVendor lütfen benzer bir soru için bana yardım edin stackoverflow.com/questions/45078720/… teşekkürler
user606669

Bu yeni nesneler yaratmaya devam etmeyecek mi?
TheRealChx101

3
   public class ServiceFactory {  
    public static ApiClient createService(String authToken, String userName, String password) {
            OkHttpClient defaultHttpClient = new OkHttpClient.Builder()
                    .addInterceptor(
                            chain -> {
                                Request request = chain.request().newBuilder()
                                        .headers(getJsonHeader(authToken))
                                        .build();
                                return chain.proceed(request);
                            })
                    .authenticator(getBasicAuthenticator(userName, password))
                    .build();
            return getService(defaultHttpClient);
        }
        private static Headers getJsonHeader(String authToken) {
            Headers.Builder builder = new Headers.Builder();
            builder.add("Content-Type", "application/json");
            builder.add("Accept", "application/json");
            if (authToken != null && !authToken.isEmpty()) {
                builder.add("X-MY-Auth", authToken);
            }
            return builder.build();
        }
        private static Authenticator getBasicAuthenticator(final String userName, final String password) {
            return (route, response) -> {
                String credential = Credentials.basic(userName, password);
                return response.request().newBuilder().header("Authorization", credential).build();
            };
        }
          private static ApiClient getService(OkHttpClient defaultHttpClient) {
            return new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .client(defaultHttpClient)
                    .build()
                    .create(ApiClient.class);
        }
}

2

Bunun gibi yerleşik yöntemleriyle Interceptors kullanarak başlıklar yapabilirsiniz.

   interceptors().add(new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request original = chain.request();

            Request.Builder builder = original.newBuilder();

            builder.header("Authorization","Bearer "+ LeafPreference.getInstance(context).getString(LeafPreference.TOKEN));

            Request request = builder.method(original.method(), original.body())
                    .build();
            Log.e("request",request.urlString());
            Log.e("header",request.header("Authorization"));
            return chain.proceed(request);
        }
    });
}

Bu yerde bağlamı nasıl elde ettiğinizi bilmek istiyorum.
rupinderjeet

@rupinderjeet Muhtemelen final Context contextparametreler listesinde bir.
TheRealChx101

@ TheRealChx101 Sadece contextburada olmamamız gerektiğini belirtmek istedim çünkü bu iş mantığı.
rupinderjeet
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.