We are going to be showing how to make a GET
request to an API that responds with a JSON
object or a JSON
array. The first thing we need to do is add the Retrofit and GSON
Converter dependencies to our module's gradle file.
Add the dependencies for retrofit library as described in the Remarks section.
Example of expected JSON object:
{
"deviceId": "56V56C14SF5B4SF",
"name": "Steven",
"eventCount": 0
}
Example of JSON array:
[
{
"deviceId": "56V56C14SF5B4SF",
"name": "Steven",
"eventCount": 0
},
{
"deviceId": "35A80SF3QDV7M9F",
"name": "John",
"eventCount": 2
}
]
Example of corresponding model class:
public class Device
{
@SerializedName("deviceId")
public String id;
@SerializedName("name")
public String name;
@SerializedName("eventCount")
public int eventCount;
}
The @SerializedName
annotations here are from the GSON
library and allows us to serialize
and deserialize
this class to JSON
using the serialized name as the keys. Now we can build the interface for the API that will actually fetch the data from the server.
public interface DeviceAPI
{
@GET("device/{deviceId}")
Call<Device> getDevice (@Path("deviceId") String deviceID);
@GET("devices")
Call<List<Device>> getDevices();
}
There's a lot going on here in a pretty compact space so let's break it down:
@GET
annotation comes from Retrofit and tells the library that
we're defining a GET request.getDevice
and takes the
device id we want as an argument.@PATH
annotation tells Retrofit that this argument should
replace the "deviceId" placeholder in the path.Call
object of type Device
.Creating a wrapper class:
Now we will make a little wrapper class for our API to keep the Retrofit initialization code wrapped up nicely.
public class DeviceAPIHelper
{
public final DeviceAPI api;
private DeviceAPIHelper ()
{
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
api = retrofit.create(DeviceAPI.class);
}
}
This class creates a GSON instance to be able to parse the JSON response, creates a Retrofit instance with our base url and a GSONConverter and then creates an instance of our API.
Calling the API:
// Getting a JSON object
Call<Device> callObject = api.getDevice(deviceID);
callObject.enqueue(new Callback<Response<Device>>()
{
@Override
public void onResponse (Call<Device> call, Response<Device> response)
{
if (response.isSuccessful())
{
Device device = response.body();
}
}
@Override
public void onFailure (Call<Device> call, Throwable t)
{
Log.e(TAG, t.getLocalizedMessage());
}
});
// Getting a JSON array
Call<List<Device>> callArray = api.getDevices();
callArray.enqueue(new Callback<Response<List<Device>>()
{
@Override
public void onResponse (Call<List<Device>> call, Response<List<Device>> response)
{
if (response.isSuccessful())
{
List<Device> devices = response.body();
}
}
@Override
public void onFailure (Call<List<Device>> call, Throwable t)
{
Log.e(TAG, t.getLocalizedMessage());
}
});
This uses our API interface to create a Call<Device>
object and to create a Call<List<Device>>
respectively. Calling enqueue
tells Retrofit to make that call on a background thread and return the result to the callback that we're creating here.
Note: Parsing a JSON array of primitive objects (like String, Integer, Boolean, and Double) is similar to parsing a JSON array. However, you don't need your own model class. You can get the array of Strings for example by having the return type of the call as Call<List<String>>
.