Java – Should I use one global Retrofit instance or create one for every request in Android?

Should I use one global Retrofit instance or create one for every request in Android?… here is a solution to the problem.

Should I use one global Retrofit instance or create one for every request in Android?

Well, I’m now lost in the process of using Retrofit… At first I wrote a Singleton helper class that contained a service instance created by a Retrofit instance. Getting the service and making HTTP requests is very convenient, but then I found out that I couldn’t get the access token from SharedPreferences because the helper instance is static. Because I use the Authenticator interface to handle authentication, I can’t pass an access token when requesting. I tried extending the Application class and saving the Application instance in a static field, but Android Studio gave me a warning (don't put the Android context class in a static field; This is a memory leak (and also breaks the Instant Run)

So now I have another option: write a static helper method that accepts an access token for each request, build a Retrofit instance, create a service instance and make the request. Now I’m confused as to if this is a best practice. What is the difference between reusing a service instance and creating a service for each request?

PS: The above service refers to the service instance created by someRetrofit.create (someServiceInterface.class), not android.app.Service

Solution

I also recommend that you continue to use the singleton method, as it is also beneficial from a design perspective.

If you create multiple service instances, each of which can have different network properties such as readTimeout, writeTimeout, response logging properties, etc., or you have to set them all to one property, this can be a headache for you if we work in a team.

One use case I’ve come across is that at a later point in time, when your backend team adds an extra header parameter for each request (like device OS version), you have to add this property to all revamped clients, which would hurt.

Here is my code fragment, how I handle headers.

public static Retrofit getRestAdapter(final HashMap<String, String> requestHeaderMap) {
    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
    OkHttpClient client = new OkHttpClient.Builder()
            .addInterceptor(interceptor)
            .addInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)
            .addNetworkInterceptor(new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request.Builder builder = chain.request().newBuilder();
                    Set<Map.Entry<String, String>> entrySet = requestHeaderMap.entrySet();
                    for (Map.Entry<String, String> entry : entrySet) {
                        if (entry.getValue().isEmpty())
                            builder.removeHeader(entry.getKey());
                        else
                            builder.addHeader(entry.getKey(), entry.getValue());
                    }

Request request = builder.build();
                    return chain.proceed(request);
                }

}).build();

return new Retrofit.Builder()
            .baseUrl(Constants.BASE_URL)
            .client(client)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
}

And the instance of requestHeaderMap is global, and data is pushed into it using observable mode.

I hope this helps you decide.

Related Problems and Solutions