Retrofit Android Get JSON From REST API Tutorial
Hi folks! Today I will share about Retrofit Android, how to get JSON data from REST API. Retrofit is one of REST API clients for Android development. This library helps to make development tasks easier to do some important things like to get and send data on the network. So It must be a waste if you don’t learn this because I personally think that this library is crucial for Android developers.
What will the app look like?
The app will look like this after you finish this tutorial:

What will you learn?
- Understand how to implement the Retrofit library on Android development.
- Understand how to get or read data from REST API on JSON format.
- Using Android RecyclerView widget to display data from REST API.
- Displaying images from URL using the Glide library.
Note: In this post, I used Android Studio 3.5.3, make sure you use the latest Android Studio, or if you already install it, be sure to check the latest update. The Kotlin version that I used is Kotlin 1.3.61.
Getting Started – Retrofit Android Get JSON From REST API
Open your Android Studio and choose to Start a new Android Studio Project. Then set the Application Name RetrofitMarvelHeroes and select Kotlin as the language. Give the Activity Name MainActivity and wait until the Android Studio finishes preparing your project.
Open app/build.gradle file and add the following codes below.
Add this code on top of the file, on the “apply plugin” section:
apply plugin: 'kotlin-kapt'
Next, put this compileOptions
code inside the android block:
android { … compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } ... }
And the last is add these dependencies inside dependencies block:
dependencies { ... implementation 'com.google.android.material:material:1.1.0' // retrofit for networking implementation 'com.squareup.retrofit2:retrofit:2.7.1' implementation 'com.squareup.retrofit2:converter-gson:2.7.1' implementation 'com.squareup.okhttp3:logging-interceptor:4.4.0' // glide to display image implementation 'com.github.bumptech.glide:glide:4.11.0' kapt 'com.github.bumptech.glide:compiler:4.11.0' ... }
The Android Material library allows you to use the RecyclerView to display the list of data that you will need later on this guide. Next, click Sync Now to begin downloading the required dependencies.
Since you will read data from the Internet, you’re gonna need to use Internet permission on Android. Open the AndroidManifest.xml file and add this <uses-permission>
code inside <manifest>
tag.
<uses-permission android:name="android.permission.INTERNET" />
Preparing the REST API Endpoint
I already prepare a REST API endpoint for this tutorial here, which is a GET type API.
https://thesimplycoder.herokuapp.com/marvel-heroes
If you open it on your browser, it will display a set of JSON data containing a list of Marvel Superheroes.
{ "code": 200, "data": [ { "_id": "5e4c22e41c9d4400004fd91b", "superhero_name": "Iron-Man", "photo": "https://thesimplycoder.com/wp-content/uploads/2020/02/iron-man.jpg", "name": "Tony Stark" }, { "_id": "5e4c233e1c9d4400004fd91c", "superhero_name": "Captain America", "photo": "https://thesimplycoder.com/wp-content/uploads/2020/02/captain-america.jpg", "name": "Steve Roger" }, { "_id": "5e4c23a61c9d4400004fd91d", "name": "Bruce Banner", "photo": "https://thesimplycoder.com/wp-content/uploads/2020/02/hulk.jpg", "superhero_name": "Hulk" }, { "_id": "5e4c23c61c9d4400004fd91e", "superhero_name": "Black Widow", "photo": "https://thesimplycoder.com/wp-content/uploads/2020/02/black-widow.jpg", "name": "Natasha Romanoff" }, { "_id": "5e4c23df1c9d4400004fd91f", "superhero_name": "Hawkeye", "photo": "https://thesimplycoder.com/wp-content/uploads/2020/02/hawkeye.jpg", "name": "Clint Barton" }, { "_id": "5e4c23fd1c9d4400004fd920", "superhero_name": "Thor", "photo": "https://thesimplycoder.com/wp-content/uploads/2020/02/thor.jpg", "name": "Thor Odinson" }, { "_id": "5e4c241a1c9d4400004fd921", "name": "Peter Parker", "photo": "https://thesimplycoder.com/wp-content/uploads/2020/02/spider-man.jpg", "superhero_name": "Spider-Man" }, { "_id": "5e4c24451c9d4400004fd922", "superhero_name": "Doctor Strange", "photo": "https://thesimplycoder.com/wp-content/uploads/2020/02/doctor-strange.jpg", "name": "Stephen Strange" }, { "_id": "5e4c24631c9d4400004fd923", "superhero_name": "Wolverine", "photo": "https://thesimplycoder.com/wp-content/uploads/2020/02/wolverine.jpg", "name": "Logan" }, { "_id": "5e4c24731c9d4400004fd924", "name": "Peter Quill", "photo": "https://thesimplycoder.com/wp-content/uploads/2020/02/star-lord.jpg", "superhero_name": "Star-Lord" }, { "_id": "5e4c25001c9d4400004fd925", "superhero_name": "Black Panther", "photo": "https://thesimplycoder.com/wp-content/uploads/2020/02/black-panther.jpg", "name": "T'challa" }, { "_id": "5e4c25331c9d4400004fd926", "name": "Scott Lang", "photo": "https://thesimplycoder.com/wp-content/uploads/2020/02/ant-man.jpg", "superhero_name": "Ant-Man" } ] }
Well, what we’re going to do is to read that data and display them on our Android app. The Retrofit will just take care of that! It will automatically convert that data to become a POJO type model on our app so you can access and read it easily. So let’s proceed to the next step.
Preparing the Data Model
Since my JSON data contain a wrapper for the data object, we need to create a wrapper class named ResponseData.kt.
package com.thesimplycoder.retrofitmarvelheroes data class ResponseData<T> ( val code: Int, val data: T )
Next, create another new Kotlin class file named Superhero.kt.
package com.thesimplycoder.retrofitmarvelheroes import com.google.gson.annotations.SerializedName class Superhero { @SerializedName("superhero_name") var superheroName: String = "" var name: String = "" var photo: String = "" }
Setting up the Retrofit
Create an interface class named ApiService.kt for listing the REST endpoint.
package com.thesimplycoder.retrofitmarvelheroes import retrofit2.Call import retrofit2.http.GET interface ApiService { @GET("marvel-heroes") fun listHeroes(): Call<ResponseData<List<Superhero>>> }
The function listHeroes()
will call the endpoint of “marvel-heroes” and will automatically convert the JSON response to a ResponseData<List<Superhero>>
object. How convenient! For more info on Retrofit action types like POST, PUT, PATCH, etc, you can go here.
Next, add a new class ApiManager.kt file.
package com.thesimplycoder.retrofitmarvelheroes import android.util.Log import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import java.util.concurrent.TimeUnit class ApiManager { private var apiService: ApiService? = null init { createService() } val service: ApiService get() = apiService!! private fun createService() { val loggingInterceptor = HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger { override fun log(message: String) { Log.i("Retrofit", message) } }) loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY val client = OkHttpClient.Builder() .readTimeout(30, TimeUnit.SECONDS) .connectTimeout(30, TimeUnit.SECONDS) .writeTimeout(30, TimeUnit.SECONDS) .addInterceptor(loggingInterceptor) .build() val retrofit: Retrofit = Retrofit.Builder() .client(client) .baseUrl("https://secret-cliffs-40396.herokuapp.com/") .addConverterFactory(GsonConverterFactory.create()) .build() apiService = retrofit.create<ApiService>(ApiService::class.java) } companion object { private var instance: ApiManager? = null fun getInstance(): ApiManager { return instance ?: synchronized(this) { ApiManager().also { instance = it } } } } }
This class is for setting up the Retrofit client. Retrofit Android uses OkHttpClient
as its networking client and GsonConverterFactory
to automatically convert the data model. On that code, I also put HttpLoggingInterceptor
to automatically logs all the API response to Android Studio Logcat for testing/debugging purposes.
Setting up RecyclerView and Data Adapter
Create a new layout file inside res/layout named item_superhero.xml.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <LinearLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:background="?selectableItemBackground" android:clickable="true" android:paddingLeft="20dp" android:paddingRight="20dp" android:paddingTop="12dp" android:paddingBottom="12dp" android:gravity="center_vertical"> <ImageView android:id="@+id/ivPhoto" android:layout_width="50dp" android:layout_height="50dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:layout_marginLeft="12dp"> <TextView android:id="@+id/tvSuperheroName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textStyle="bold" android:textSize="16sp" android:text="Superhero Name" /> <TextView android:id="@+id/tvName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="2dp" android:text="Name" /> </LinearLayout> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="#dedede" /> </LinearLayout>
After that, add a new class SuperheroAdapter.kt file.
package com.thesimplycoder.retrofitmarvelheroes import android.content.Context import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import com.bumptech.glide.load.engine.DiskCacheStrategy import kotlinx.android.synthetic.main.item_superhero.view.* class SuperheroAdapter : RecyclerView.Adapter<SuperheroAdapter.ViewHolder>() { private lateinit var itemList: List<Superhero> lateinit var context: Context override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { context = parent.context val view = LayoutInflater.from(context).inflate(R.layout.item_superhero, parent, false) return ViewHolder(view) } override fun getItemCount(): Int { return if (::itemList.isInitialized) itemList.size else 0 } override fun onBindViewHolder(holder: ViewHolder, position: Int) { holder.bind() } fun updateData(list: List<Superhero>) { itemList = list; notifyDataSetChanged() } inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { fun bind() { val item = itemList.get(adapterPosition) itemView.tvName.text = item.name itemView.tvSuperheroName.text = item.superheroName Glide.with(context) .load(item.photo) .diskCacheStrategy(DiskCacheStrategy.ALL) .circleCrop() .into(itemView.ivPhoto) } } }
It is just a typical Adapter code for Android RecyclerView. If you want to learn more about working with Android RecyclerView, you can go here.
Open the activity_main.xml file inside the res/layout directory and replace the layout code:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/rvData" android:layout_width="match_parent" android:layout_height="match_parent" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" /> <ProgressBar android:id="@+id/pbLoading" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" /> </RelativeLayout>
After that, open the MainActivity.kt file and replace the code like this:
package com.thesimplycoder.retrofitmarvelheroes import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.util.Log import android.view.View import kotlinx.android.synthetic.main.activity_main.* import retrofit2.Call import retrofit2.Callback import retrofit2.Response class MainActivity : AppCompatActivity() { val TAG = MainActivity::class.java.name val itemList = ArrayList<Superhero>() lateinit var adapter: SuperheroAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // initialize adapter adapter = SuperheroAdapter() rvData.adapter = adapter // call api to get the data from network loadData() } private fun loadData() { // show loading progress bar pbLoading.visibility = View.VISIBLE ApiManager.getInstance().service.listHeroes() .enqueue(object : Callback<ResponseData<List<Superhero>>> { override fun onResponse( call: Call<ResponseData<List<Superhero>>>, response: Response<ResponseData<List<Superhero>>> ) { val listData: List<Superhero> = response.body()!!.data // updating data from network to adapter itemList.clear() itemList.addAll(listData) adapter.updateData(itemList) // hide loading progress bar pbLoading.visibility = View.GONE } override fun onFailure(call: Call<ResponseData<List<Superhero>>>, t: Throwable) { // if there is error while get data from network Log.e(TAG, "Error on loading data") pbLoading.visibility = View.GONE } }) } }
The loadData()
function is to load data or call the marvel-heroes endpoint using the Retrofit client. When getting the data is successful, it will execute the onResponse()
callback so that you could update your data list here. On the other hand, the onFailure()
callback only invoked when there is an error while getting data.
Try run your app and see what happens!

Where to go next?
You can download this full code from the link below:
Be sure to check my other cool posts here about:
- Bottom Navigation Bar Android Using Kotlin
- Android RecyclerView Tutorial Using Kotlin
- Copy to Clipboard Using Kotlin on Android
- Android Take Photo from Camera and Gallery
I hope you like my post, comment and share it with love!