What is Retrofit?
Retrofit is an Android Library useful for API Calls on a network. Retrofit turns your HTTP API into a Java interface.
It is developed by Square A company developed many famous Open Source project for Android and Java. Some of them are Picasso(Image Loading Library), Otto (An event Bus).
What is new in Retrofit 2.0?
- Declaration for synchronous and asynchronous API calls made same.
Retrofit 2 gives Call<T> object for calling any API. Which can be canceled later on. - The converter is now excluded from Retrofit. You have to use converters of your choice separately.
- It makes library very tinyHere is the list of official Converter modules provided by Square.
- Choose one that fits your requirement best.
- Gson: com.squareup.retrofit:converter-gson
- Jackson: com.squareup.retrofit:converter-jackson
- Moshi: com.squareup.retrofit:converter-moshi
- Protobuf: com.squareup.retrofit:converter-protobuf
- Wire: com.squareup.retrofit:converter-wire
- Simple XML: com.squareup.retrofit:converter-simplexml
In below example we will fetch data from github.com for any github user.
for that we will use API provided by github on https://api.github.com/users
You can checkout api response which we are going to use is
https://api.github.com/users/dudhatparesh
You can click on above url and change last name as your wish to see different type of result.
Download Code
Example:
Lets Build:
1) Create A New Project In Android Studio with Empty Activity.
2) Give Activity name as “MainActivity.java” & Layout as “activity_main.xml”.
3) add following line in AndroidManifest.xml
1 |
<uses-permission android:name="android.permission.INTERNET"/> |
4) Now add following dependencies in your app level build.gradle file
1 2 3 4 5 |
compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0' compile 'com.google.code.gson:gson:2.7' ompile 'com.squareup.okhttp3:logging-interceptor:3.4.1' compile 'com.squareup.okhttp3:okhttp:3.4.1' |
5) Create a RestClient class in your application and add following Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
public class RestClient { private static RestClient restClient; Retrofit retrofit; private WebServices webServices; private String baseUrl; private RestClient(String baseUrl) { HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); logging.setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient httpClient = new OkHttpClient.Builder() .connectTimeout(100, TimeUnit.SECONDS) .addInterceptor(logging) .readTimeout(100, TimeUnit.SECONDS) .build(); retrofit = new Retrofit.Builder().baseUrl(baseUrl).addConverterFactory( GsonConverterFactory.create( new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() .create())) .client(httpClient) .build(); this.baseUrl = baseUrl; webServices = retrofit.create(WebServices.class); } public static RestClient getInstance() throws Exception { if (restClient == null) { restClient = new RestClient("https://api.github.com/"); } return restClient; } public WebServices getWebServices() { return webServices; } } |
Here
RestClient.getInstance() will give you singleton object of this class.
In
RestClient() constructor we first create an instance of
HttpLoggingInterceptor . It will be used for showing request and response body in Log.
Then we create an instance of OkHttpClient it will be useful for two reason
i) adding
HttpLoggingInterceptor
ii) setting the different type of timeouts for API call such as readTimeout,connectionTimeout or WriteTimeOut.
Now we will create an instance of Retrofit using builder pattern. Now we have to create an interface “WebServices.java”.
Add following code into WebServices.java file
1 2 3 4 |
public interface WebServices { @GET("users/{username}") Call<User> getUser(@Path("username") String username); } |
Here we have added API methods
First of all, we have to specify method type we want to use for API call.
@GET , @POST , @PUT, @DELETE, @UPDATE etc
Then it will be followed by end points.
For Ex,
We have API URLs as
https://api.github.com/users/{username}
Then https://api.github.com/ will be in our baseURL in RestClient.java.
And “users/{username}” will be in WebServices.
Like @GET(“users/{username}”)
Then we will specify Call<T> where T is response class as the return type of method.
If API requires the multipart request or FormData request then we have to specify @Multipart, @FormUrlEncoded.
In GET request or POST with JSON request does not need extra annotations
For POST(FormData) request we have to specify request as the @Field parameter.
For POST(Multipart) request we have specified request as @Part.
For POST(JSON) request we have to specify request as @Body with Request Class.
For @GET request, we can specify @Query or @Path Parameter.
8) Now we will create response classes required in WebServices.
Create User.java file and add following code into it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
class User { @SerializedName("message") @Expose private String expose; @SerializedName("avatar_url") @Expose private String avatarUrl; @SerializedName("name") @Expose private String name; @SerializedName("company") @Expose private String company; @SerializedName("location") @Expose private String location; @SerializedName("email") @Expose private String email; @SerializedName("html_url") @Expose private String htmlURL; public String getExpose() { return expose; } public void setExpose(String expose) { this.expose = expose; } public String getAvatarUrl() { return avatarUrl; } public void setAvatarUrl(String avatarUrl) { this.avatarUrl = avatarUrl; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCompany() { return company; } public void setCompany(String company) { this.company = company; } public String getLocation() { return location; } public void setLocation(String location) { this.location = location; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getHtmlURL() { return htmlURL; } public void setHtmlURL(String htmlURL) { this.htmlURL = htmlURL; } } |
Now we have completed all configuration for our first API call on api.github.com
To execute get user API In MainActivity.java first we need to setup activity_main.xml file.
Add following code into activity_main.xml file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="16dp" android:gravity="center" android:orientation="vertical" tools:context="com.enggdream.retrofitdemo.MainActivity"> <EditText android:id="@+id/et_username" android:layout_width="wrap_content" android:layout_height="wrap_content" android:hint="@string/enter_user_name" /> <Button android:id="@+id/btn_get_data" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/get" /> <TextView android:id="@+id/tv_message" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <LinearLayout android:id="@+id/ll_user_data_container" android:visibility="gone" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="100dp" android:layout_height="wrap_content" android:text="@string/name" /> <TextView android:layout_width="32dp" android:layout_height="wrap_content" android:text="@string/divider" /> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="100dp" android:layout_height="wrap_content" android:text="@string/company" /> <TextView android:layout_width="32dp" android:layout_height="wrap_content" android:text="@string/divider" /> <TextView android:id="@+id/tv_company" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="100dp" android:layout_height="wrap_content" android:text="@string/location" /> <TextView android:layout_width="32dp" android:layout_height="wrap_content" android:text="@string/divider" /> <TextView android:id="@+id/tv_location" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="100dp" android:layout_height="wrap_content" android:text="@string/email" /> <TextView android:layout_width="32dp" android:layout_height="wrap_content" android:text="@string/divider" /> <TextView android:id="@+id/tv_email" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" /> </LinearLayout> </LinearLayout> </LinearLayout> |
Add following code in MainActivity.java file
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
public class MainActivity extends AppCompatActivity { TextView tvName, tvCompany, tvLocation, tvEmail, tvMessage; Button btnGetData; EditText etUsername; ProgressDialog progressDialog; LinearLayout llUserDataContainer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvName = (TextView) findViewById(R.id.tv_name); tvCompany = (TextView) findViewById(R.id.tv_company); tvLocation = (TextView) findViewById(R.id.tv_location); tvEmail = (TextView) findViewById(R.id.tv_email); tvMessage = (TextView) findViewById(R.id.tv_message); llUserDataContainer = (LinearLayout) findViewById(R.id.ll_user_data_container); btnGetData = (Button) findViewById(R.id.btn_get_data); etUsername = (EditText) findViewById(R.id.et_username); btnGetData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { getUserData(); } }); } public void getUserData() { //Close Keyboard InputMethodManager inputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); inputManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); //Set User data container visibility gone llUserDataContainer.setVisibility(View.GONE); //Setup ProgressDialog progressDialog = new ProgressDialog(this); progressDialog.setTitle("Please wait"); progressDialog.setMessage("We are fetching user data."); progressDialog.setCancelable(false); progressDialog.show(); String username = etUsername.getText().toString(); //Make API Call RestClient.getInstance().getWebServices().getUser(username).enqueue( new Callback<User>() { @Override public void onResponse(Call<User> call, Response<User> response) { if (!MainActivity.this.isFinishing() && progressDialog.isShowing()) progressDialog.dismiss(); if (response.isSuccessful()) { if (TextUtils.isEmpty(response.body().getMessage())) { tvMessage.setText(""); User user = response.body(); llUserDataContainer.setVisibility(View.VISIBLE); tvName.setText(user.getName()); tvEmail.setText(user.getEmail()); tvLocation.setText(user.getLocation()); tvCompany.setText(user.getCompany()); } else { tvMessage.setText(response.body().getMessage()); } } else { tvMessage.setText("Status:" + response.code() + "\nMessage:" + response.message()); } } @Override public void onFailure(Call<User> call, Throwable t) { if (MainActivity.this.isFinishing() && progressDialog.isShowing()) progressDialog.dismiss(); tvMessage.setText(t.getLocalizedMessage()); } }); progressDialog.show(); } } |
Here we have callback which includes two methods
1)onResponse
2)onFailure
onResponse will be called when an app is able to connect with a server. However, we have to check whether the response is successful or not.
If server response cannot be parsed or server sends something other than 200 code.
Then we will get response.isSuccessful as false.
In this case, we will simply show a message with response.message() text.
If a response is successful then we can access java object converted from a response. (Here User) by response.body().
If there is network problem or any other such issue when app is not able to connect with remote server then
onFailure will be called so we show user exception message in the TextView by calling t.getLocalizedMessage().
You can download the source code from the following URL.
https://github.com/EnggDream/retrofit2demo
Thanks for this blog. It’s easy way to use for GET method but i am getting problem in POST so I need one demo where easily post request and get data.
Thank you for reading this article,
We are writing an article on POST with Retrofit as well.
Hello Paresh,
Is there any update?