Retrofit 2 Basic Ideas

 

 What is Retrofit?

The official page describes Retrofit as "A type-safe REST client for Android and Java."
You’ll use annotations to describe HTTP requests, URL parameter replacement and query parameter support is integrated by default. Additionally, it provides functionality for custom headers, multipart request body, file uploads and downloads, mocking responses and much more.

Client Interface

The following code defines the GitHubClient and a method reposForUser to request the list of repositories for a given user.


public interface GitHubClient { 
    @GET("/users/{user}/repos")
    Call<List<GitHubRepo>> reposForUser(
        @Path("user") String user
    );
}


Retrofit’s basis for all requests is the Retrofit (2.0+) class.  you can use the builder to set some general options for all requests, i.e. the base URL or the converter. Once you’ve created an adapter, you’re able to create a client. You’ll use the client to execute the actual requests.

            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .build();
           GitHubClient client =  retrofit.create(GitHubClient.class); 


In Retrofit 2, you also use your client object. You use the client to get a call object. Once you’ve invoked .enqueue on the created call object the request will be made by Retrofit. There is also an option to do a synchronous request.


// Create a very simple REST adapter which points the GitHub API endpoint.
GitHubClient client =  retrofit.create(GitHubClient.class);
// Fetch a list of the Github repositories.
Call<List<GitHubRepo>> call = 
    client.reposForUser("fs-opensource");
// Execute the call asynchronously. Get a positive or negative callback.
call.enqueue(new Callback<List<GitHubRepo>>() { 
    @Override
    public void onResponse(Call<List<GitHubRepo>> call, Response<List<GitHubRepo>> response) {
        // The network call was a success and we got a response
        // TODO: use the repository list and display it
    }
    @Override
    public void onFailure(Call<List<GitHubRepo>> call, Throwable t) {
        // the network call was a failure
        // TODO: handle error
    }
});

Basics of API Description

Annotations on the interface methods and its parameters indicate how a request will be handled.


public interface GitHubClient { 
    @GET("/users/{user}/repos")
    Call<List<GitHubRepo>> reposForUser(
        @Path("user") String user
    );
}


Retrofit provides an annotation for each of the main standard request methods. You simply use the appropriate Retrofit annotations for each HTTP method: @GET, @POST, @PUT, @DELETE, @PATCH or @HEAD. If you never heard of HTTP request methods, read up on it on wikipedia’s HTTP page.
A request URL can be updated dynamically using replacement blocks and parameters on the method. A replacement block is an alphanumeric string surrounded by { and }. A corresponding parameter must be annotated with @Path using the same string.


@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);


Query parameters can also be added.


@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);


For complex query parameter combinations a Map can be used.


@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);


the method's return type is critical. In all those cases, you'll have to wrap it into a typed Retrofit Call<> class. An invocation of a Retrofit method that sends a request to a webserver and returns a response. Each call yields its own HTTP request and response pair. Use clone() to make multiple calls with the same parameters to the same webserver; this may be used to implement polling or to retry a failed call.
Calls may be executed synchronously with execute(), or asynchronously with enqueue(retrofit2.Callback<T>). In either case the call can be canceled at any time with cancel(). A call that is busy writing its request or reading its response may receive a IOException; this is working as designed.
Finally, and this highly depends on the API endpoint, you can pass parameters to the method. There is a wide variety of possible options, so we’ll just link you some options:
@Body: send Java objects as request body.
@Url: use dynamic URLs.
@Field: send data as form-urlencoded.


public interface FutureStudioClient { 
    @GET("/user/info")
    Call<UserInfo> getUserInfo();
    @PUT("/user/info")
    Call<Void> updateUserInfo(
        @Body UserInfo userInfo
    );
    @GET
    Call<ResponseBody> getUserProfilePhoto(
        @Url String profilePhotoUrl
    );
}


Form-encoded data is sent when @FormUrlEncoded is present on the method. Each key-value pair is annotated with @Field containing the name and the object providing the value.


@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);


Multipart requests are used when @Multipart is present on the method. Parts are declared using the @Part annotation.


@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);


HEADER MANIPULATION

You can set static headers for a method using the @Headers annotation.


@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call<List<Widget>> widgetList();
@Headers({
    "Accept: application/vnd.github.v3.full+json",
    "User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);


Note that headers do not overwrite each other. All headers with the same name will be included in the request.
A request Header can be updated dynamically using the @Header annotation. A corresponding parameter must be provided to the @Header. If the value is null, the header will be omitted. Otherwise, toString will be called on the value, and the result used.


@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)


Headers that need to be added to every request can be specified using an OkHttp interceptor.

Comments