user5988366
user5988366

Reputation:

Design pattern for retrofit interface

I have trouble with the design of my Retrofit interface creator. I want to be able to instanciate the API interface in a generic way and update the corresponding instance whenever a token is passed. Currently, when I update the token, I have to call createService() method again to get the new instance that used the token in the generation of the Interface...

Somebody asked for a similar question but never got an answer here

public class RetrofitCreator {

    private static String TAG = "RetrofitCreator";
    private static String WSSE = null;
    private static String AmzToken = null;
    static HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    private static AmazonAPI amazonAPI = null;
    private static VanishAPI cobaltAPI = null;

    //static OkHttpClient client = new OkHttpClient.Builder().build();
    static OkHttpClient.Builder httpClient = new OkHttpClient.Builder().addInterceptor(interceptor.setLevel(HttpLoggingInterceptor.Level.BODY));

    private static Retrofit.Builder builder =
            new Retrofit.Builder();

    public static <S> S createService(Class<S> serviceClass) {

        S mAPI = null;
            if(serviceClass.getSimpleName().equals("VanishAPI")){
                if(VanishAPI==null){
                    VanishAPI = (VanishAPI) createVanishAPI(serviceClass);
                }
                mAPI = (S) VanishAPI;
            }else if(serviceClass.getSimpleName().equals("AmazonAPI")){
                if(amazonAPI==null){
                    amazonAPI = (AmazonAPI) createAmazonAPI(serviceClass);
                }
                mAPI = (S) amazonAPI;
            }
        return mAPI;
    }


    public static void setWSSE(String WSSE) {
        RetrofitCreator.WSSE = WSSE;
        vanishAPI = createVanishAPI(VanishAPI.class);
    }

    public static void setAmzToken(String token) {
        RetrofitCreator.AmzToken = token;
        amazonAPI = createAmazonAPI(AmazonAPI.class);
    }

private static <S> S createAmazonAPI(Class<S> serviceClass){
    httpClient = getUnsafeOkHttpClient();
    builder = new Retrofit.Builder()
            .baseUrl(Constants.URL_AMAZON)
            .addConverterFactory(JacksonConverterFactory.create());

    if (AmzToken != null) {
        Log.w(TAG, "WSSE not null!");
        Interceptor interceptorSecure = new Interceptor() {
            @Override
            public Response intercept(Interceptor.Chain chain) throws IOException {
                Request original = chain.request();

                // Request customization: add request headers
                Request.Builder requestBuilder = original.newBuilder()
                        .header("Cache-Control", "no-cache")
                        .header("Accept", "application/json")
                        .header("Authorization", "Bearer " + AmzToken)
                        .method(original.method(), original.body());

                Request request = requestBuilder.build();
                return chain.proceed(request);
            }
        };
        httpClient.addInterceptor(interceptorSecure);
    }

    OkHttpClient client = httpClient.build();
    Retrofit retrofit = builder.client(client).build();
    return retrofit.create(serviceClass);
}

(...)
}

To get it in each Activity I use :

amazonApi = RetrofitCreator.createService(AmazonAPI.class);

Upvotes: 5

Views: 1183

Answers (1)

Ilya Tretyakov
Ilya Tretyakov

Reputation: 7010

Make your interceptor look like this:

public class TokenInterceptor implements Interceptor {

    private String token;

    public String getToken() {
        return token;
    }

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

            // Request customization: add request headers
            Request.Builder requestBuilder = original.newBuilder()
                    .header("Cache-Control", "no-cache")
                    .header("Accept", "application/json")
                    .method(original.method(), original.body());
            if (getToken() != null) {
                requestBuilder.header("Authorization", "Bearer " + AmzToken);
            }
            Request request = requestBuilder.build();
            return chain.proceed(request);
    }

    public void setToken(String token) {
        this.token = token;
    }
}

Add it to you OkHttp client and keep reference to this interceptor. Now you don't have to call createService() after each token change. Just change token in interceptor via interceptor.setToken()

Upvotes: 2

Related Questions