Close
Close full mode
logoAppDevAssist

How to load data in RecyclerView from API in Android(Kotlin)

How to load data in RecyclerView from API:

In our previous tutorial, we learned how to show data in a RecyclerView. In this tutorial, we will learn how to fetch data from an API and load it into the RecyclerView.

This post will focus on loading the data from the API.

YouTube video:

Data to load:

The app will load the following data:

[
{
"id" : 1,
"title" : "Autumn leaves",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididun",
"image" : "https://cdn.pixabay.com/photo/2020/10/03/17/40/autumn-5624139_1280.jpg"
},
{
"id" : 2,
"title" : "Alpine mountains",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididun",
"image" : "https://cdn.pixabay.com/photo/2020/10/03/10/56/mountains-5623208_1280.jpg"
},
{
"id" : 3,
"title" : "Mountain climbing adventure",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididun",
"image" : "https://cdn.pixabay.com/photo/2016/11/08/05/20/adventure-1807524_1280.jpg"
},
{
"id" : 4,
"title" : "Northen light Aurora",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididun",
"image" : "https://cdn.pixabay.com/photo/2016/02/07/19/48/aurora-1185464_1280.jpg"
},
{
"id" : 5,
"title" : "Polar Bear",
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididun",
"image" : "https://cdn.pixabay.com/photo/2013/10/16/14/04/polar-bear-196318_1280.jpg"
}
]

I created a simple Node.js application that will return this JSON array.

Node.js Application:

Download the Node.js application from this link. You can run npm install && npm run start or yarn && yarn start to run this app. It will start the server on the 3000 port.

Open a browser and go to localhost:3000, it will show you the above JSON array.

Android Studio project:

Let's create one basic Android Studio project and change it as described below:

Dependencies:

Add the following dependencies to the project:

dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version'
implementation 'androidx.core:core-ktx:1.1.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.cardview:cardview:1.0.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.moshi:moshi-kotlin:1.11.0'
implementation 'com.squareup.retrofit2:converter-moshi:2.9.0'
implementation 'com.github.bumptech.glide:glide:4.11.0'
}

A few of these dependencies will be added by default to the project Android Studio will create. We have added the following dependencies:

  • RecyclerView: To show the content in a list.
  • CardView
  • Retrofit: To get the data from the API
  • Moshi: JSON converter to convert the JSON data.
  • Glide: To load the image into the list item.

Sync the project after you add the dependencies.

AndroidManifest.xml:

Following is the content of the AndroidManifest file used by the project:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapplication">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:usesCleartextTraffic="true"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
  • We need to add permission for Internet.
  • We need to use usesCleartextTraffic as true as we have to use cleartext network traffic.

Model class:

Create one class Property.kt with the following:

package com.example.myapplication.models
data class Property(val id: Int, val title: String, val description: String, val image: String)

This is a data class to hold the JSON data objects.

activity_main.xml:

This is the layout file of the activity:

<?xml version="1.0" encoding="utf-8"?>
<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">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="1dp"
android:layout_marginLeft="1dp"
android:layout_marginTop="25dp"
android:layout_marginEnd="1dp"
android:layout_marginRight="1dp"
android:layout_marginBottom="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

It has one RecyclerView.

list_item.xml:

This is the layout file for each RecyclerView list item:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView android:layout_height="wrap_content"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardCornerRadius="8dp"
app:cardElevation="8dp"
android:layout_margin="5dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintWidth_percent=".3"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
android:src="@drawable/ic_launcher_background"
/>
<TextView
android:id="@+id/tvTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@+id/imageView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:textSize="25sp"
android:fontFamily="sans-serif"
android:textColor="#212121"
android:layout_marginStart="10dp"
android:text="This is a very long title and here it is"
android:layout_marginLeft="10dp" />
<TextView
android:id="@+id/tvDescription"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="@+id/tvTitle"
app:layout_constraintEnd_toEndOf="@id/tvTitle"
app:layout_constraintTop_toBottomOf="@+id/tvTitle"
app:layout_constraintBottom_toBottomOf="parent"
android:textSize="18sp"
android:fontFamily="sans-serif"
android:text="This is a very long title and here it is"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

RecyclerView adapter:

Create one file MyAdapter.kt to use as the RecyclerView adapter:

package com.example.myapplication
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.myapplication.models.Property
import org.w3c.dom.Text
class MyAdapter(private val data: List<Property>) : RecyclerView.Adapter<MyAdapter.MyViewHolder>() {
class MyViewHolder(val view: View): RecyclerView.ViewHolder(view){
fun bind(property: Property){
val title = view.findViewById<TextView>(R.id.tvTitle)
val imageView = view.findViewById<ImageView>(R.id.imageView)
val description = view.findViewById<TextView>(R.id.tvDescription)
title.text = property.title
description.text = property.description
Glide.with(view.context).load(property.image).centerCrop().into(imageView)
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false)
return MyViewHolder(v)
}
override fun getItemCount(): Int {
return data.size
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.bind(data[position])
}
}
  • It takes the data as the data source to load to the RecyclerView.
  • It uses the list_item layout to show the data to a RecyclerView item.
  • To load the image in the ImageView, it uses Glide.

ApiService:

Create one file ApiService.kt to write the retrofit API calls:

package com.example.myapplication.network
import com.example.myapplication.models.Property
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import retrofit2.http.GET
private const val BASE_URL = "http://10.0.2.2:3000"
private val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
private val retrofit = Retrofit.Builder().addConverterFactory(MoshiConverterFactory.create(moshi)).baseUrl(BASE_URL).build()
interface ApiService{
@GET(".")
fun getAllData(): Call<List<Property>>
}
object Api {
val retrofitService: ApiService by lazy{retrofit.create(ApiService::class.java)}
}
  • We are using the base url as 10.0.2.2 as this is the localhost url for emulators.
  • The retrofit builder uses moshi as the converter.
  • The getAllData method is used to get the data from the BASE_URL. It converts the data to a list of Property object.

MainActivity:

The code of MainActivity is:

package com.example.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.myapplication.models.Property
import com.example.myapplication.network.Api
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class MainActivity : AppCompatActivity() {
private lateinit var recyclerView: RecyclerView
private lateinit var manager: RecyclerView.LayoutManager
private lateinit var myAdapter: RecyclerView.Adapter<*>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
manager = LinearLayoutManager(this)
getAllData()
}
fun getAllData(){
Api.retrofitService.getAllData().enqueue(object: Callback<List<Property>>{
override fun onResponse(
call: Call<List<Property>>,
response: Response<List<Property>>
) {
if(response.isSuccessful){
recyclerView = findViewById<RecyclerView>(R.id.recycler_view).apply{
myAdapter = MyAdapter(response.body()!!)
layoutManager = manager
adapter = myAdapter
}
}
}
override fun onFailure(call: Call<List<Property>>, t: Throwable) {
t.printStackTrace()
}
})
}
}
  • It calls the getAllData function to load the data by using the API service.
  • Once the data is received, it creates one adapter and assigns that adapter to the RecyclerView.
  • The RecyclerView uses a LinearLayoutManager as we are showing the data in a vertical list.

Output:

It will give the below output:

RecyclerView load data from API
RecyclerView load data from API

Github:

The code is available on Github. Please use the tut-2 tag to get the code explained on this tutorial.

git clone https://github.com/AppDevAssist/recyclerview-kotlin && git checkout tags/tut-2

Subscribe to our Newsletter

Previous
How to create a RecyclerView with a complex layout in Android(Kotlin)
Next
How to delete item from RecyclerView in Android(Kotlin)