If you have ever tried downloading and parsing JSON data on Android, you might know how much of a pain it can be. If you use HttpUrlConnection
, a typical request might look like the following:
HttpURLConnection c = null;
URL u = new URL("https://codeship.com/api/v1/api/v1/projects/" + projectId + ".json");
c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setConnectTimeout(5);
c.setReadTimeout(5);
c.connect();
int status = c.getResponseCode();
InputStream in = c.getInputStream();
// etc
...
All that is without parsing the status codes and catching the many exceptions that could be thrown. Even then, you still need to parse the JSON for each individual key.
Retrofit is "A type-safe REST client for Android and Java".
Although Retrofit is not a new tool, it is very powerful and makes a huge difference when developing and maintaining a project. Add it as a dependency of your project with compile 'com.squareup.retrofit:retrofit:1.9.0'
.
Lets take the Codeship API as an example:
A list of all builds for a project can be retrieved from the endpoint GET /api/v1/projects/:project_id.json
. A CodeshipService
interface can be created, which defines the method for this API route, like below:
public interface CodeshipService {
@GET("/projects/{project_id}.json")
void getProject(@Path("project_id") String projectId, Callback<Project> cb);
}
@GET
part is called an annotation. This provides a form of metadata indicating how the request should be handled.@Path
annotated parameter below.<Project>
represents the object that the JSON response will be converted into.The Codeship documentation defines the JSON structure of a project
as follows:
{
"id": 33837,
"repository_name": "codeship/documentation",
"uuid": "59a737f0-1648-0132-c4e7-72c6c37b1f6e",
"builds": [ … ]
}
this can be represented as a Java object (POJO):
public class Project {
public String id;
public String uuid;
public List<Build> builds;
public String getId() {
return id;
}
public List<Build> getBuilds() {
return builds;
}
}
Once the interface and entities have been created and all the API routes that will be used have been defined, it can be implemented into RETROFIT adapter. I recommend creating a custom class to wrap the service, this makes configuration much easier, and reusable.
public class Codeship {
public CodeshipService service;
public Codeship(final String apiKey) {
// Create the restAdapter, setting the base url
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://codeship.com/api/v1")
// Codeship requires an API key, so add this in to each request
.setRequestInterceptor(new RequestInterceptor() {
@Override
public void intercept(RequestInterceptor.RequestFacade request) {
request.addQueryParam("api_key", apiKey);
}
})
.build();
this.service = restAdapter.create(CodeshipService.class);
}
}
The following method can then use the interface created earlier:
public void getProject(String projectId, Callback<Project> cb) {
service.getProject(projectId, cb);
}
Now that all the pieces have been created, we can make use of our new API service:
// Create the Codeship service
Codeship cs = new Codeship(apiKey);
cs.getProject("123123", new Callback<Project>() {
@Override
public void success(Project project, Response response) {
// Update the UI and show the project information
List<Build> builds = project.getBuilds();
}
@Override
public void failure(RetrofitError error) {
// Handle the error and show an appropriate message to the user
}
});
This code can be easily reused all over your application, without needing to set options each time. If Codeship decides to make a change to their API routes, the interface and service can be quickly changed without affecting the rest of your code.
Retrofit 2.0 is due out by the end of 2015 and promises to bring a host of new features and improvements. Version 2.1 should also bring support for websockets. [^1]
*Edit (2016): Since writing this article, Retrofit 2.0 has been released, I recommend reading this article for an overview of the new features and syntax changes.*
[^1]: Source: https://speakerdeck.com/jakewharton/simple-http-with-retrofit-2-droidcon-nyc-2015