Retrofit is a REST Client for Android. It makes it easy to retrieve and upload JSON (or other structured data) via a REST based webservice. It uses OkHttp library for making HTTP requests.

Retrofit can be configured with different converters for data serialization.

We will be using Retrofit 2.

To work with Retrofit, we require following:

  1. A Model class to map JSON data
  2. An interface which defines all HTTP operations
  3. Library to convert JSON data to Java Objects, we will be using GSON

Example

Let us create an Android example to see how Retrofit works.

  1. Create a new android project named retro in Android studio (I’m using version 2.0). Set company domain to example.
  2. Select Add No Activity on the next steps.
  3. Open your build.gradle (Module app) file and add following dependencies in the dependencies section:
    compile 'com.google.code.gson:gson:2.6.2'
    compile 'com.squareup.retrofit2:retrofit:2.1.0'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
  4. Next add the internet permission to the manifests/AndroidManifest.xml file:
    <uses-permission android:name="android.permission.INTERNET"/>
  5. Next we will create a model that will map Java Objects to JSON. Create a new package example.retro.model and create a class Employee in it. Here is the class:
    package example.retro.model;
    
    public class Employee {
        
        private String name;
        private int id;
        
        public Employee(){
        }
        
        public Employee(int id, String name){
            this.id = id;
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    }
  6. Now we will create interface that uses Retrofit for REST API calls. Create a new package example.retro.api and create an interface named EmployeeAPI. Here is the interface:
    package example.retro.api;
    
    import java.util.List;
    
    import example.retro.model.Employee;
    import retrofit2.Call;
    import retrofit2.http.GET;
    import retrofit2.http.Path;
    
    public interface EmployeeAPI {
    
        @GET("/retroweb/api/employees/list")
        public Call<List<Employee>> getEmployees();
    
        @GET("/retroweb/api/employees/find/{id}")
        public Call<Employee> getEmployee(@Path("id") Integer id);
    }
  7. Next we will create two activities to list employees as well as show single employee. Let us create two activities:
    Create a new blank activity named ActivityEmployee.java with activity_employee.xml as the layout file. This activity will have a simple ListView. Here is the code:
    activity_employee.xml

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:context="example.retro.activity.ActivityEmployee">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
    
            <ListView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/listViewEmployees">
    
            </ListView>
    
        </LinearLayout>
    
    </android.support.design.widget.CoordinatorLayout>

    ActivityEmployee.java

    package example.retro.activity;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    
    import retrofit2.Call;
    import retrofit2.Callback;
    import retrofit2.Response;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import example.retro.R;
    import example.retro.api.EmployeeAPI;
    import example.retro.model.Employee;
    import retrofit2.Retrofit;
    import retrofit2.converter.gson.GsonConverterFactory;
    
    public class ActivityEmployee extends AppCompatActivity {
    
        private ListView listViewEmployees;
    
        // On command prompt, use the command ipconfig to get ip address
        // of your local computer. Connect your phone and computer on same network
        private static String ROOT_URL = "http://192.168.1.4/";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_employee);
    
            listViewEmployees = (ListView) findViewById(R.id.listViewEmployees);
    
            getEmployees();
        }
    
        private void getEmployees() {
    
            //Creating a rest adapter
            Retrofit adapter = new Retrofit.Builder()
                    .baseUrl(ROOT_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
    
            //Creating an object of our api interface
            EmployeeAPI api = adapter.create(EmployeeAPI.class);
    
            Call<List<Employee>> call = api.getEmployees();
    
            // make an asynchronous call
            call.enqueue(new Callback<List<Employee>>() {
                @Override
                public void onResponse(Call<List<Employee>> call, Response<List<Employee>> response) {
                    List<Employee> employees = response.body();
    
                    showEmployees(employees);
                }
    
                @Override
                public void onFailure(Call<List<Employee>> call, Throwable t) {
    
                }
            });
        }
    
        private void showEmployees(List<Employee> employees) {
    
            ArrayList<String> employeeNames = new ArrayList<>();
    
            for (Employee employee : employees)
                employeeNames.add(employee.getName());
    
            ArrayAdapter adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, employeeNames);
    
            listViewEmployees.setAdapter(adapter);
        }
    }

    activity_single_employee.xml

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:context="example.retro.activity.ActivitySingleEmployee">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:padding="10dp">
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:text=""
                android:id="@+id/tvId"/>
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textAppearance="?android:attr/textAppearanceLarge"
                android:text=""
                android:id="@+id/tvName"
                android:layout_gravity="center_vertical"
                android:layout_marginTop="20dp" />
        </LinearLayout>
    
    </android.support.design.widget.CoordinatorLayout>

    ActivitySingleEmployee.java

    package example.retro.activity;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import example.retro.R;
    import example.retro.api.EmployeeAPI;
    import example.retro.model.Employee;
    import retrofit2.Call;
    import retrofit2.Callback;
    import retrofit2.Response;
    import retrofit2.Retrofit;
    import retrofit2.converter.gson.GsonConverterFactory;
    
    public class ActivitySingleEmployee extends AppCompatActivity {
    
        private TextView tvId;
        private TextView tvName;
    
        private static String ROOT_URL = "http://192.168.1.4/";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_single_employee);
    
            tvId = (TextView)findViewById(R.id.tvId);
            tvName = (TextView)findViewById(R.id.tvName);
    
            // read the passed employee id
            String passedId = getIntent().getExtras().getString("id");
    
            if(passedId != null) {
                int id = Integer.parseInt(passedId);
    
    
                getEmployee(id);
            }
            else
                Toast.makeText(getBaseContext(), "No id passed", Toast.LENGTH_LONG);
        }
    
        private void getEmployee(int id) {
    
            //Creating a rest adapter
            Retrofit adapter = new Retrofit.Builder()
                    .baseUrl(ROOT_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
    
            //Creating an object of our api interface
            EmployeeAPI api = adapter.create(EmployeeAPI.class);
    
            Call<Employee> call = api.getEmployee(id);
    
            // make an asynchronous call
            call.enqueue(new Callback<Employee>() {
                @Override
                public void onResponse(Call<Employee> call, Response<Employee> response) {
                    Employee employee = response.body();
    
                    showEmployee(employee);
                }
    
                @Override
                public void onFailure(Call<Employee> call, Throwable t) {
    
                }
            });
        }
    
        private void showEmployee(Employee employee) {
    
            tvId.setText(String.valueOf(employee.getId()));
            tvName.setText(employee.getName());
        }
    }
  8. You can use any technology to get server side data in the form of JSON. Here I will be using PHP Slim MVC framework for server side.
    Create a new folder named retroweb under your apache web folder ( htdocs, www etc. )
    Create a new file named composer.json in this folder with following code:

    {
        "require": {
            "slim/slim": "^3.4"
        }
    }
  9. Make sure you have composer installed on your system. On the command prompt or terminal, move into the retroweb folder and execute following commands:
    composer install
    
    composer update

    This will download slim files in vendor folder.

  10. Now create index.php file with following code:
    <?php
    use \Psr\Http\Message\ServerRequestInterface as Request;
    use \Psr\Http\Message\ResponseInterface as Response;
    
    /********************** basic slim settings ********************/
    require 'vendor/autoload.php';
    
    $config = array();
    
    $app = new \Slim\App(["settings" => $config]);
    
    unset($app->getContainer()['errorHandler']);
    
    $container = $app->getContainer();
    $container['view'] = new \Slim\Views\PhpRenderer("templates/");
    
    /********************* now our configuration ******************/
    
    class Employee{
       var $id;
       var $name;
    
       function __construct($id, $name)
       {
          $this->id = $id;
          $this->name = $name;
       }
    }
    
    $employees = array(
       new Employee(1, "Ashutosh"),
       new Employee(2, "Gautam"),
       new Employee(3, "Shankar")
    );
    
    $app->get('/api/employees/list', function () use($employees) {
       echo json_encode($employees);
    });
    
    $app->get('/api/employees/find/{id}', function (Request $request, Response $response, $args) use($employees) {
    
       $id = $args['id'];
    
       foreach($employees as $employee)
       {
          if($employee->id == $id){
             echo json_encode($employee);
             break;
          }
    
          echo null;
       }
    });
    
    $app->run();
  11. Now we have following URLs ready for our app:
    http://localhost/retroweb/api/employees/list
    
    http://localhost/retroweb/api/employees/find/1
  12. Go ahead and execute your mobile app.