Very often, Android applications are connected to backend services and consume REST services to get data. When you think to that kind of apps, you can imagine an application that displays weather to a user and get data from a backend service. Or you can imagine a Todo client that stores todos on server to offer users to check their todos in their browser too. Whereas it’s not very complicated to communicate with a REST service, get data at JSON format and parse them to display, it becomes quickly a pain.

To improve your productivity and gain some time when you make that kind of application, it’s better to use a dedicated framework. Offered by Square, Retrofit is a framework that lets you to make easy REST in Android. You can even combine Retrofit with GSON framework and simplify your JSON parsing like we’re going to see it in the following tutorial.

  1. REST Service in JSON Format

Here, we’re going to get Todos stored on a server and exposed via a REST service at the following URL : http://ssaurel.com/tmp/todos . Like you can see, there are to JSON format :


{
 "todos" :
  [
   {
    "id": 1,
    "title": "Todo 1",
    "completed": false
   },
   {
    "id": 2,
    "title": "Todo 2",
    "completed": false
   },
   {
    "id": 3,
    "title": "Todo 3",
    "completed": true
   }
  ]
}

It would be good too to be able to request for a specific Todo. REST Service offering us that feature will have the following URL : http://ssaurel.com/tmp/1/todo . Result will be also in JSON format :


{  "id": 1,  "title": "Todo 1",  "completed": false}

 

  1. Generate Model for the REST Service

First, we need to generate a model of POJO Java classes that will let us to manipulate Todos. A great tool to generate that model is available here : http://www.jsonschema2pojo.org/ . Json Schema 2 Pojo lets us to generate POJO Java classes associated to a JSON sample of results. We use the previous sample of JSON data and we choose the package name (com.ssaurel.retrofit) and the main class for the Model. Like we wanna use GSON, we choose GSON Annotation Style on POJO.

json2pojo

 

With Json Schema 2 Pojo, we obtain 2 POJO Java classes :

– Result


package com.ssaurel.retrofit;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

import java.util.ArrayList;
import java.util.List;

public class Result {

@SerializedName("todos")
@Expose
private List<Todo> todos = new ArrayList<Todo>();

 /**
 *
 * @return
 * The todos
 */
 public List<Todo> getTodos() {
  return todos;
 }

 /**
 *
 * @param todos
 * The todos
 */
 public void setTodos(List<Todo> todos) {
  this.todos = todos;
 }

}

 

– Todo


package com.ssaurel.retrofit;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class Todo {

 @SerializedName("id")
 @Expose
 private Integer id;
 @SerializedName("title")
 @Expose
 private String title;
 @SerializedName("completed")
 @Expose
 private Boolean completed;

 /**
 *
 * @return
 * The id
 */
 public Integer getId() {
  return id;
 }

 /**
 *
 * @param id
 * The id
 */
 public void setId(Integer id) {
  this.id = id;
 }

 /**
 *
 * @return
 * The title
 */
 public String getTitle() {
  return title;
 }

 /**
 *
 * @param title
 * The title
 */
 public void setTitle(String title) {
  this.title = title;
 }

 /**
 *
 * @return
 * The completed
 */
 public Boolean getCompleted() {
  return completed;
 }

 /**
 *
 * @param completed
 * The completed
 */
 public void setCompleted(Boolean completed) {
  this.completed = completed;
 }

}

Later, we could use these classes in our Android application.

 

  1. Download and Install Retrofit

Offered by Square, Retrofit is detailed here : http://square.github.io/retrofit/ . To install it in an Android project, we can use the following Gradle dependency :

 

compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'

Besides, we wanna use GSON parsing from the data we got from the REST Service. So, we must add the GSON Converter dependency :

 

compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'

Add these dependecies in your build.gradle in your Android Studio project.

 

  1. Create the REST Service in the Android Application

In the Android application, we must define an interface that exposes services we wanna offer in the application. Here, we will have two methods : one to get all todos and one to get a specific todo via its id.


package com.ssaurel.retrofit;

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;

public interface GetTodos {

 @GET("tmp/todos")
 Call<Result> all();

 @GET("tmp/{id}/todo")
 Call<Todo> select(@Path("id") int id);
}

For each method associated to a REST service, we define the path and the HTTP method to request server. Here, it’s GET Method. In the select method, we tell to Retrofit that the parameter id will be use to build the path of the REST service called thanks to @Path annotation.

 

  1. Configure Retrofit in the Android Application

Now, we need to configure Retrofit in the Android Application by defining the End Point of the REST Service and the converser used to parse data got. Here, we will use a GsonConverter object :


Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ENDPOINT_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();

To create an instance of our REST Service GetTodos, we must just call the create method of Retrofit instance created previously :


GetTodos getTodos = retrofit.create(GetTodos.class);

 

  1. Get All Todos from the REST Service

With our GetTodos service, we can get all the todos from the REST Service. It’s very easy like you see below :


Call<Result> call = getTodos.all();
Response<Result> response = call.execute();
Result result = response.body();

 

  1. Get a specific Todo from the REST Service

It’s the same thing to get a specific Todo from the REST Service :


Call<Todo> call = getTodos.select(id);
Response<Todo> response = call.execute();
Todo result = response.body();

 

  1. Create User Interface of the Android Application

To test these REST Services calls, we need to create a small User Interface for the Android Application. So, we define a simple layout with a multilines TextView and two Buttons : one to load all Todos and one to load a specific Todo :


<RelativeLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:paddingLeft="@dimen/activity_horizontal_margin"
 android:paddingRight="@dimen/activity_horizontal_margin"
 android:paddingTop="@dimen/activity_vertical_margin"
 android:paddingBottom="@dimen/activity_vertical_margin"
 tools:context=".MainActivity">

 <TextView android:id="@+id/resultTv"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:maxLines="10"
  android:textSize="18sp"
  android:layout_marginTop="50dp"
  android:layout_centerHorizontal="true"/>

 <Button
  android:id="@+id/allBtn"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="All"
  android:layout_below="@+id/resultTv"
  android:layout_marginTop="10dp"
  android:layout_centerHorizontal="true"/>

 <Button
  android:id="@+id/oneBtn"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="Get One"
  android:layout_below="@+id/allBtn"
  android:layout_marginTop="10dp"
  android:layout_centerHorizontal="true"/>

</RelativeLayout>

 

  1. And now, the Main Activity

We put all in place in the Main Activity :


package com.ssaurel.retrofit;

import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import java.io.IOException;
import java.util.List;

import retrofit2.Call;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class MainActivity extends ActionBarActivity {

 private static final String ENDPOINT_URL = "http://www.ssaurel.com";
 private Button allBtn;
 private Button oneBtn;
 private TextView resultTv;
 private Retrofit retrofit;
 private GetTodos getTodos;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  retrofit = new Retrofit.Builder()
   .baseUrl(ENDPOINT_URL)
   .addConverterFactory(GsonConverterFactory.create())
   .build();
  getTodos = retrofit.create(GetTodos.class);

  allBtn = (Button) findViewById(R.id.allBtn);
  allBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      loadTodos();
    }
  });

  oneBtn = (Button) findViewById(R.id.oneBtn);
  oneBtn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      loadTodo(1);
    }
  });

  resultTv = (TextView) findViewById(R.id.resultTv);
 }

 private void loadTodos() {
  new Thread(new Runnable() {

   @Override
   public void run() {
     Call<Result> call = getTodos.all();

     try {
       Response<Result> response = call.execute();
       final Result result = response.body();

       runOnUiThread(new Runnable() {

         @Override
         public void run() {
           displayResult(result);
         }
       });

     } catch (IOException e) {
    }
   }
  }).start();

 }

 private void displayResult(Result r) {
   if (r != null) {
    List<Todo> todos = r.getTodos();
    String tmp = "";

    for (Todo todo : todos) {
      tmp += todo.getId() + " | " + todo.getTitle() + " | " + (todo.getCompleted()? "Done" : "To Do") + "\n\n";
    }

    resultTv.setText(tmp);

   } else {
    resultTv.setText("Error to get todos");
   }
 }

 private void loadTodo(final int id) {
   new Thread(new Runnable() {

    @Override
    public void run() {
      Call<Todo> call = getTodos.select(id);

      try {
        Response<Todo> response = call.execute();
        final Todo result = response.body();

        runOnUiThread(new Runnable() {

          @Override
          public void run() {
            displayTodo(result);
          }
        });

      } catch (IOException e) {

      }

    }
   }).start();

 }

 private void displayTodo(Todo todo) {
  if (todo != null) {
   String tmp = todo.getId() + " | " + todo.getTitle() + " | " + (todo.getCompleted()? "Done" : "To Do") + "\n";
   resultTv.setText(tmp);

  } else {
   resultTv.setText("Error to get todo");
  }
 }

}

Tricky part is the call of the REST Service that must made in a different Thread that UI Thread. So, we create a new Thread. Then, when we get the result of the call, we display the result in the UI Thread via a call to runOnUiThread() method.

 

  1. Final touch with the demo

Now, we can try our Android Application by calling 2 REST Services and enjoy the result :

Retrofit Screen 1

 

Retrofit Screen 2

 

Like you can see, Retrofit lets you to consume REST Services easily and makes your life easier. Don’t hesitate and give it a try !