1

I am referencing this post Where to keep Retrofit Adapter in Android App? but I am not allowed to comment there due to stackoverflow limitations [thank you stackoverflow for treating new users like kids].

Where does the Retrofit RestAdpater go when using Android? Can anybody please elaborate on @Jake Wharton 's answer of above post.

When I place the RestAdapter in my Activity, it will probably get GCed when the Activity is destroyed, so the Singleton loses its reference and needs to be recreated the next time (I assume).

Further, the first thing that I did for testing is exactly this and Android tells me I cannot do a network request on the Main thread. I understand that I can't do that, but I thought Retrofit would automatically create a separate thread for me.

Will I need to create an AsyncTask to host the RestAdapter? Or how exactly does this work for Android? Where is the adapter best instantiated? Which is the recommended point to attach the Retrofit reference?

Community
  • 1
  • 1
Oliver Hausler
  • 4,900
  • 4
  • 35
  • 70

1 Answers1

2

So what @JakeWharton was saying is that the RestAdapter and the api interface instances should be created once. How you achieve that is pretty much an implementation details.

In a straight forward manner you could create a class which would hold a single instance to your RestAdapter. You would be responsible of making only a single instance of that class. You'd probably want to hold a reference to this class in your Application class. You could also approach this using the Singleton pattern

Here's a small class to get you started. I took this from a previous post which you can see here

public class RestApiDispencer {
    private Map<String, Object> restApiInstances = new HashMap<String, Object>();
    private RestAdapter restAdapter;

    public RestApiDispencer(RestAdapter restAdapter) {
        this.restAdapter = restAdapter;
    }

    public <T> T getRestApi(Class<T> clazz) {
            T client = null;
            if ((client = (T) restApiInstances.get(clazz.getCanonicalName())) != null) {
                return client;
            }
            client = restAdapter.create(clazz);
            restApiInstances.put(clazz.getCanonicalName(), client);
            return client;
    }
}

If you're familiar with dependency injection then that would be another way to go. Personally I prefer to use dependency injection when it comes to hiding implementation details from use.

Creating the RestAdapter directly into your Activity would not the way you'd want to go. Instead in your activity would want to get a reference to this RestApiDispencer class from above and have it return the instance of the rest api of your choise by providing its class like so.

MyClassApi myClassApi = restApiDispencer.getRestApi(MyClassApi.class);

There are other ways to achieve this but as I said it's up to you to decide which implementation fits best your needs.

As for Retrofit doing request on a separate thread, yes it does but you need to create your Api interfaces accordingly.

@GET(/some/rest/api/path)
Response getApiData() // Synchronous declaration as the Response is returned from the method.

@GET(/some/rest/api/path)
void getApiData(Callback<Response> callback); // Asynchronous as the Response is delivered in the callback.

@GET(/some/rest/api/path)
Observable<Response> getApiData(); // Asynchronous again but you'll need to read up on rx-java before using this. 

Read on rx-java here

So if you do decide to create your rest api by using the asynchronous signature then you won't have to worry about threading when invoking your interface. If you use the synchronous signature then it's all up to you.

Community
  • 1
  • 1
Miguel
  • 19,793
  • 8
  • 56
  • 46
  • thank you for your detailed answer. You are saying "You'd probably want to hold a reference to this class in your Application class. You could also approach this using the Singleton pattern". Application class reference is clear, but what about the Singleton and GC in Android? Does the Singleton block itself from being garbage collected without a reference? Example: I use a singleton and instantiate it from the Activity, as suggested, but I don't keep the reference anywhere around. The static code block in the Singleton stays instantiated for the consecutive access. But what about GC? – Oliver Hausler Aug 13 '14 at 13:48
  • I wanted to add a link: http://portabledroid.wordpress.com/2012/05/04/singletons-in-android/ - it's quite confusing how many opinions are around regarding this topic and how different they are. – Oliver Hausler Aug 13 '14 at 14:24
  • 1
    If by Singleton were talking about a class with a "static" member, then it would not be garbage collected as static members are not part of the heap. This means in Android world that the same Singleton instance would be available for the duration of the "Process". If your process disappears which it could well possibly do, your Singleton would have to be recreated. As for your example, no it will not be garbage collected for the same reason I've just mentioned. – Miguel Aug 13 '14 at 14:34