4

Well, I am lost in using Retrofit now... At first I write a Singleton helper class which hold a service instance created by a Retrofit instance. It is very convenient to get the service and make HTTP request, but then I find that I can't get the access token from SharedPreferences, because the helper instance is static. Because I use the Authenticator interface to deal with the authentication, it is not possible to pass the access token when making request. I try to extend Application class and hold the Application instance in static field, but Android Studio give me a warning(Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)).

So now I have another choice: write a static helper method that, for each request, accepts the access token, build a Retrofit instance, create a service instance and make the request. Now I am confusing that whether this is a best practice. What's the difference between reusing one service instance and creating service for each request?

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

Perqin
  • 755
  • 10
  • 27
  • funny that on my project it doesn't give this warning about memory leak. But Anyway, that's only a warning. There's nothing wrong in holding a static reference to the application. I have an answer about it here http://stackoverflow.com/questions/14057273/android-singleton-with-global-context/14057777#14057777 . So my suggestion is to just use the single application and don't worry about this warning. – Budius Aug 08 '16 at 14:54
  • @Budius Actually I also want to know the difference between reusing single instance created by `someRetrofit.create(xxx.class)` and doing this at each request. – Perqin Aug 08 '16 at 16:29
  • I never dig too deep there, but it seems that the instance would be controlling/holding the threads, callbacks, interceptors, so it's something that you probably should not be creating a new one every time. – Budius Aug 08 '16 at 18:21

1 Answers1

-1

I would also suggest you to go ahead with Singleton approach only,as its good from design prospective also .

If you create multiple instance of service each one of them could have different network properties like readTimeout , writeTimeout , response logging property , etc or you would have to set them all to one single property and if our working in team this could give you alot of headache.

And a usercase which i faced was , at some later point of time your backend team as you to on additional header param to each request like device os version then you would have to add this property to all the retrofit client which would be a pain .

Here is snippet of my code , 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 is instance of requestHeaderMap is global instance and data is being pushed into it using observable pattern .

I hope this could help you to take a decision .

Code_Life
  • 5,742
  • 4
  • 29
  • 49