Android network call using Retrofit library

Retrofit : A type-safe HTTP client for Android and Java.

Nowadays, a Smart phone becoming a trend. And hence the scope of Android is increasing continuously. But we also need security while transferring our data on the network. So here is a type-safe library which takes care of the security while making network calls in Android programming.

Retrofit is used to make network calls (REST). This is an annotation based library by Square.

It reduces the long code and makes server calls in few lines of code, which also reduces the time and efforts of a developer.

There are five built-in annotations in Retrofit GET, POST, PUT, DELETE, and HEAD. We will see few of them in brief later.

 Let’s see a sample first

Very first thing, add below dependencies in your project build.gradle(Module: app) file,

compile 'com.google.code.gson:gson:2.6.2'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'

Second, add an internet permission in AndroidManifest.xml file because we are dealing with network,

<uses-permission android:name="android.permission.INTERNET"/>

Now, Create a new class to create an instance of Retrofit with base Url of your backend API.

public class ApiClient implements Constant {
private static Retrofit retrofit = null;

public static Retrofit getClient() {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_BACKEND_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}

Next, create an interface which will have an actual call to the server, let’s called it ApiInterface.java

public interface ApiInterface {
  @GET("endpoint/user/get_all/")  //this is the rest api url
   Call<Response> getAllUsers(@Query("api_key") String apiValue);

    /* You can also specify query parameters in the URL.
      The response of above and this below query will be same. */
    
    @GET("endpoint/style/all/?api_key=apiValue")
    Call<RegionResponse> getAllUsers();

}

 

Next, create another class, which will hold the response returned by the API.
Here, @SerializedName(“response”) is a key of the response object.

public class Response {

@SerializedName("response")
private ArrayList<ResponseModel> results;

public ArrayList<ResponseModel> getResults() {
return results;
}
public void setResults(ArrayList<ResponseModel> results) {
this.results = results;
}
}

Create a model class(pojo class) to hold the response for each object. @SerializedName holds the key of the field.

public class ResponseModel {

@SerializedName("id")
private String id;
@SerializedName("name")
private String name;
@SerializedName("image")
private String imageUrl;

public ResponseModel (String id, String name, String imageUrl){
super();
this.id = id;
this.name = name;
this.imageUrl = imageUrl;

}

public String getId(){
return id;
}
public void setId(String id){
this.id = id;
}
public String getImageUrl(){
return imageUrl;
}
public void setImageUrl(String imageUrl){
this.imageUrl = imageUrl;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}

}

Now finally, lets make a call from the activity. Let’s create it!

public class MainActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create instance of get Retrofit instance and connect with the network call methods.
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);

// Make a call to specific server API
Call<ResponseObject> call = apiService.getAllUsers(API_KEY);
call.enqueue(new Callback<ResponseObject>() {
@Override
public void onResponse(Call<ResponseObject> call, retrofit2.Response<ResponseObject> response) {
// Here you will get the response.
int statusCode = response.code();
ArrayList<ResponseModel> responseModel = response.body().getResults();
Log.e(TAG, "onResponse: statusCode = "+statusCode+" responseModel = "+responseModel);
// Now you can set your adapter for RecyclerView etc...
}

@Override
public void onFailure(Call<com.ilandmusic.retrofit.Response> call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
}
}

Give a try to above code and I hope you will be able to make the first request of server API using the Retrofit library!

 

Understand use of Retrofit

Retrofit supports
* query parameter support
* Object conversion to request body (e.g., JSON, protocol buffers)
* Multipart request body and file upload

Built-in annotations :

GET Method
Lets see how we can get list of all users just by writing couple of lines.

@GET("endpoint/user/get_all/")
Call<Response> getAllUsers(@Query("api_key") String apiValue);

You can also specify query parameters in the URL. The response of above and this below query will be same.

@GET("endpoint/user/get_all/?api_key=apiValue")
Call<Response> getAllUsers();

Also can specify the path, as shown below example,

@GET("endpoint/user/{id}")
Call<Response> getUserDetails(@Path("id") int id, @Query("api_key") String apiValue);

You can send headers by defining @Headers annotation on request call method or as a parameter to the request call method with @Header annotation. Below example explain itself.

@Headers({
"api_key: Api-value",
"token: Tokan-value"
})
@GET("endpoint/user/{id}")
Call<Response> getUserDetails(@Path("id") int id);

POST Method
An object can be specified for use as an HTTP request body with the @Body annotation. Below example shows how we can make a POST server call,

@POST("endpoint/user/create")
Call<User> createUser(@Body User user);

If you are using converter on Retrofit instance, the object user will be converted using it. If no converter is added, only RequestBody can be used as a object. Above query can be,

@POST("endpoint/user/create")
Call<User> createUser(@Body RequestBody user);

If you want to send sensitive data but without @Body, like user details over a network, no worries, Retrofit has the @FormUrlEncoded annotation. @FormUrlEncoded this will encode the data in form of key-value pair which will be annotated with @Field containing the name and the object providing the value.

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

PUT Method
You can send Multipart requests by using @Multipart annotation on the request call method. Parts are declared using the @Part annotation.

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