Android REST Client: Retrofit

A really important issue from the guys of Square, Inc. has been its contribution to the developers community through Square Open Source [1], releasing outstanding libraries aim to accelerate the development time.

Today we will talk about Retrofit, a REST client for Android –and java- that we currently use in “Vamos al Cine!” app for Android.

Why use Retrofit?

Three reasons:

  • Development speed: Is not necessary to reinvent the wheel, if your app works with a web service to send/receive data, this library will probably handle all what you need.
  • Resources optimization: Square is valued in 6 billion dollars [2], I tend to think the code their engineers write will be more optimized than the one I produce.
  • Fewer bugs: The library is used by many developers (5,679 stars and 948 forks in github at the time this was written), which means a lot of errors already fixed, the same errors we could encounter creating our own implementation.

Development

WHAT ARE WE GOING TO ACHIEVE?

We are going to have a news app. The user selects a topic and the app get news about that topic through a webservice. Information about the author of the news can also be consulted.

INCLUDING RETROFIT

First we have to add the Gradle dependence:

compile 'com.squareup.retrofit:retrofit:1.9.0'

The library requires at least Java 6 and Android 2.3

MODEL

One of the advantages of Retrofit is that it allows automatically mapping the JSON answers to Java objects. Here we will create the model classes:

public class News {

    String title;
    String date;
    String body;
    int id_author;

}
public class Author {

    int id;
    String name;
    String email;
}

API REST INTERFACE

Now we will create the Java Interface which contains the calls to the REST API 

public interface NewsServiceAPI {

    //url_base/api/news?news_type=news_type
    @GET("/api/news")
    List<News> getNews(@Query("news_type") String news_type);

    //url_base/api/authors/3
    @GET("/api/authors/{author_id}")
    Author getAuthor(@Path("author_id") int author_id);

    //url_base/api/news?news_type=news_type
    @GET("/api/news")
    void getNewsAsync(@Query("news_type") String news_type, Callback<List<News>> callback);
}

Here we can see three calls to the web service. The first method getNews() requires a parameter about which topic of news we would like to get. In getAuthor() it is required to use the author id to get the data.

In the first and second method we can see that the return is mapped to the class of the model we defined previously. The third method is different because it is asynchronous and it has to define a Callback to manage the answer, I will talk about this later on.

REST Client

This class will use the interface and will be instantiated when we want to make the calls:

public class NewsRestClient {

        private static final String BASE_URL = "http://base_url";
        private NewsServiceAPI apiService;

        public NewsRestClient()
        {

            RestAdapter restAdapter = new RestAdapter.Builder()
                    .setLogLevel(RestAdapter.LogLevel.FULL)
                    .setEndpoint(BASE_URL)
                    .build();

            apiService = restAdapter.create(NewsServiceAPI.class);
        }

        public NewsServiceAPI getApiService()
        {
            return apiService;
        }
}

The base url needs to be set in the direction in which the webservice is located. The method setLogLevel() allows to see valuable information to see what the library is doing “underneath”, headers, server responses, error codes and others can be seen. In the construction of the adapter, some other aspects can be customized, like the JSON converter used, the error manager and including headers. For more details check the official documentation.

SYNCHRONOUS CALL

Now we will make use of our super implementation and we will call the webservice using our REST client to get the news:

public void getNews(String news_type){

    NewsRestClient restClient = new NewsRestClient();

    List<News> news = restClient.getApiService().
getNews(news_type);
    /*
     * Here we have the news and can be displayed
     */

}

We can see that the client is instantiated and a call is made using as a parameter the type of news. The library handles the formatting of the REST call. Our app directly gets a list of News objects, convenient huh?

Is relevant to say this call is synchronic, which means, it will block the execution until it gets a response, this isn’t good if it executed from the main thread, that’s why synchronic methods should be executed in another thread, for example, in an AsyncTask[3]. It would also be good to control the exceptions that can occur with a try-catch block.

Now we will see that the function to obtain the author is really similar:

public void getAutor(int id_author){

    NewsRestClient restClient = new NewsRestClient();

    Author author = restClient.getApiService().getAuthor(id_author);
    /*
     * Here we can make use of the author data
     */
}

ASYNCHRONOUS CALL

To the asynchronous methods we have to add a Callback method that will handle the response, once it arrives.

public void getNewsAsync(String news_type){

    NewsRestClient restClient = new NewsRestClient();

    restClient.getApiService().getNewsAsync(news_type,new CallBackNews());

}

And here is the Callback class:

private class CallBackNews implements Callback<List<News>>{

    @Override
    public void success(List<News> news, Response response) {
        //Here do something with the news.. save them¿?
    }

    @Override
    public void failure(RetrofitError error) {
        //Handle the errors
    }
}

And the implementation is complete.

 

[1]http://square.github.io/
[2] http://techcrunch.com/2014/10/05/square-closes-150-round-at-6-billion-valuation/
[3]http://developer.android.com/reference/android/os/AsyncTask.html

Leave a Reply

Your email address will not be published. Required fields are marked *