Introduction to Retrofit in Android
Retrofit is a type-safe HTTP client for Android, developed by Square. It simplifies network operations by allowing developers to define REST API interactions using Java/Kotlin interfaces. It supports various request methods like GET, POST, PUT, DELETE, and PATCH while enabling seamless integration with JSON parsing libraries like Gson and Moshi.
Why Use Retrofit?
The advantages that Retrofit has over traditional network handling methods like HttpURLConnection and Volley are:
- Provides a clean and simple way to define API requests.
- Converts API responses directly into Java/Kotlin objects, making it type safe.
- Supports both asynchronous calls (using enqueue) and synchronous calls (using execute).
- Allows adding custom headers, logging, and authentication easily.
- Can be extended with converter, thus highly scalable.
Step by Step Implementation:
In this article, we will be implementing the GET request method. To know more about the other request methods refer to
- How to Post Data to API using Retrofit in Android?
- How to Update Data in API using Retrofit in Android?
Step 1: Add necessary dependencies
For using Retrofit in our Android project firstly we have to add dependency in the gradle file. For adding dependency open app/build.gradle file in your Android project and add the following lines inside it. Add these lines inside dependencies{}
dependencies {
implementation ("com.google.code.gson:gson:2.9.1")
implementation ("com.squareup.retrofit2:retrofit:2.9.0")
implementation ("com.squareup.retrofit2:converter-gson:2.9.0")
}
Step 2: Provide internet permission
We should now add Internet Permission inside Manifest file. Open the AndroidManifest.xml file and add the following line.
<uses-permission android:name="android.permission.INTERNET"/>
Step 3: Create a model class for data response from API
For retrieving data from the server using retrofit 2 we require a model class. We are going to make a model class to retrieve data from the server. Set the name of the class ResponseData.

ResponseData Class:
package org.geeksforgeeks.demo;
import com.google.gson.annotations.SerializedName;
public class ResponseData {
@SerializedName("body")
private String body;
@SerializedName("id")
private int id;
@SerializedName("title")
private String title;
@SerializedName("userId")
private int userId;
public ResponseData(String body, int id, String title, int userId) {
this.body = body;
this.id = id;
this.title = title;
this.userId = userId;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
}
package org.geeksforgeeks.demo
data class ResponseData(
val body: String,
val id: Int,
val title: String,
val userId: Int
)
Step 4: Create a Retrofit Object/Instance
Create an retrofit instance to define API base url.
RetrofitInstance Class:
package org.geeksforgeeks.demo;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofitInstance {
private static final String BASE_URL = "https://jsonplaceholder.typicode.com";
private static Retrofit retrofit;
public static Retrofit getRetrofitInstance() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
public static ApiInterface getApiInterface() {
return getRetrofitInstance().create(ApiInterface.class);
}
}
package org.geeksforgeeks.demo
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
object RetrofitInstance {
private val retrofit by lazy {
Retrofit.Builder().baseUrl("https://jsonplaceholder.typicode.com")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
val apiInterface by lazy {
retrofit.create(ApiInterface::class.java)
}
}
Step 5: Create a API interface
Create an interface to define API endpoints and their request types.
ApiInterface Class:
package org.geeksforgeeks.demo;
import retrofit2.Call;
import retrofit2.http.GET;
public interface ApiInterface {
@GET("/posts/1")
Call<ResponseData> getData();
}
package org.geeksforgeeks.demo
import retrofit2.Call
import retrofit2.http.GET
interface ApiInterface {
@GET("/posts/1")
fun getData(): Call<ResponseData>
}
Step 6: Working with activity_main.xml
Navigate to app > res > layout > activity_main.xml and make the below changes. We will be adding 2 textviews and a button to fetch the data.
activity_main.xml:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/title_textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:text="Title"
android:textSize="24sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/body_textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<TextView
android:id="@+id/body_textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="32dp"
android:text="Body"
android:textSize="16sp"
android:textStyle="italic"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/title_textView" />
<Button
android:id="@+id/getData_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="Get Data"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/body_textView" />
</androidx.constraintlayout.widget.ConstraintLayout>
Design UI:

Step 7: Working with MainActivity file
In this file, we will call the Retrofit Instance to get the data and bind it to the view. Navigate to app > kotlin+java > {package-name} > MainActivity.java/MainActivity.kt and make the necessary changes given below.
MainActivity File:
package org.geeksforgeeks.demo;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MainActivity extends AppCompatActivity {
private TextView titleTextView;
private TextView bodyTextView;
private Button getDataButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
titleTextView = findViewById(R.id.title_textView);
bodyTextView = findViewById(R.id.body_textView);
getDataButton = findViewById(R.id.getData_button);
getDataButton.setOnClickListener(view -> getData());
}
private void getData() {
ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Please wait");
progressDialog.show();
RetrofitInstance.getApiInterface().getData().enqueue(new Callback<ResponseData>() {
@Override
public void onResponse(Call<ResponseData> call, Response<ResponseData> response) {
ResponseData responseData = response.body();
if (responseData != null) {
titleTextView.setText(responseData.getTitle());
bodyTextView.setText(responseData.getBody());
}
progressDialog.dismiss();
}
@Override
public void onFailure(Call<ResponseData> call, Throwable t) {
Toast.makeText(MainActivity.this, t.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
progressDialog.dismiss();
}
});
}
}
package org.geeksforgeeks.demo
import android.app.ProgressDialog
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class MainActivity : AppCompatActivity() {
private lateinit var titleTextView: TextView
private lateinit var bodyTextView: TextView
private lateinit var getDataButton: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
titleTextView = findViewById(R.id.title_textView)
bodyTextView = findViewById(R.id.body_textView)
getDataButton = findViewById(R.id.getData_button)
getDataButton.setOnClickListener {
getData()
}
}
private fun getData() {
val progressDialog = ProgressDialog(this)
progressDialog.setMessage("Please wait")
progressDialog.show()
RetrofitInstance.apiInterface.getData().enqueue(object : Callback<ResponseData?> {
override fun onResponse(call: Call<ResponseData?>, response: Response<ResponseData?>) {
val responseData = response.body()
titleTextView.text = responseData?.title
bodyTextView.text = responseData?.body
progressDialog.dismiss()
}
override fun onFailure(call: Call<ResponseData?>, t: Throwable) {
Toast.makeText(this@MainActivity, t.localizedMessage, Toast.LENGTH_SHORT).show()
progressDialog.dismiss()
}
})
}
}