Create a List in Android using RecyclerView — Part 1

Rohit Rawat
7 min readMar 5, 2020

Welcome to the first article in ‘Create List in Android using RecyclerView’ Series.

Introduction, some boring stuff

RecyclerView is an Android ViewGroup by definition, meaning it is designed to contain other Android views like Button, TextView, EditText etc. It is basically used to implement lists and grid in Android. Although ListView and GridView are already there but RecyclerView is used the most. Reason being, it can render horizontal, vertical, grid and staggered lists with a slight change of lines of code.

I’ll write about these different Views soon. PS: This tutorial is meant for absolute beginner and beginner level Android Developers.

Okay enough talking, let’s get on with it.

Create New Project

First of all, create a new Android Project in Android Studio and select Empty Activity for now.

Create a new Android Project
Create a new Android Project in Android Studio

Add RecyclerView Dependency

RecyclerView doesn’t come with legacy Android library. So we need to download it from the Android Repository. This is achieved something called Dependency in Android. To install the RecyclerView dependency, open your app level build.gradle file and navigate to dependencies section.

Open app level build.gradle file

Add the following line in the dependency section of the file.

implementation ‘androidx.recyclerview:recyclerview:1.1.0’
Add the dependency for RecyclerView and click on Sync Now

Then click on ‘Sync Now’ on the top right and let the dependency get loaded. FYI, you need to have an active Internet for this. Once the gradle build is done, we can start writing some code. 🌝

Giving our App a UI

Think. Where do we need to show the list? Inside the RecyclerView obviously. So, go to activity_main.xml and write the following code in it. Here, we have added a RecyclerView to the view hierarchy inside LinearLayout.

<?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"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_movies"
android:layout_height="match_parent"
android:layout_width="match_parent"
tools:listitem="@layout/row_movie"
/>
</LinearLayout>

Do you watch Movies?

We chose to show some static movies data in our list. We are following MVC kind of pattern here. What this means is that we have a Model, a View and a Controller of these two. In simple words, Model contains data, View is where the data is loaded and Controller the transactions between Model and View. OTH, right? Don’t stress it too much if you don’t get things now, you will, but for now let’s write it out.

Proceed to creating a model class named Movie.java. Objects of this class will contain the data fields which we want to store and display in the RecyclerView.

Create new Java class named Movie.java

Now write the following code in the Movie.java class.

public class Movie {
private String name;
private String year;
private String directorName;
public Movie(String name, String directorName, String year) {
this.name = name;
this.directorName = directorName;
this.year = year;
}
public String getName() {
return name;
}
public String getDirectorName() {
return directorName;
}
public String getYear() {
return year;
}
}

Where do you watch movies?

On screens for sure. But here in Android we use row views to show anything like movies in a list. Please note that we are not going to play movies here. To keep the article simple we are using just TEXTS.

Now we will be creating a row layout file to contain a view inside the RecyclerView. Create a new layout file named row_movie.xml and write the following code in it.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="5dp">
<TextView
android:id="@+id/txt_movie_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/string_movie_name"
android:padding="4dp"
android:textColor="@android:color/black"
android:textSize="22sp" />
<TextView
android:id="@+id/txt_director_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/string_director_name"
android:padding="4dp"
android:textSize="18sp" />
<TextView
android:id="@+id/txt_year"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/string_year"
android:padding="4dp"
android:textSize="18sp" />
</LinearLayout>

A ViewHolder to… Hold Views

We are now in the position of defining a ViewHolder class. But wait, what is a ViewHolder?

ViewHolder is a class which holds the data that is to be shown in the UI for each view inside the RecyclerView.

Create a new class named MovieViewHolder.java and write the following code in it.

import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.cradle.recyclerviewexample.R;public class MovieViewHolder extends RecyclerView.ViewHolder { private TextView txtMovieName;
private TextView txtDirectorName;
private TextView txtYear;
public MovieViewHolder(@NonNull View itemView) {
super(itemView);
txtDirectorName = itemView.findViewById(R.id.txt_director_name);
txtMovieName = itemView.findViewById(R.id.txt_movie_name);
txtYear = itemView.findViewById(R.id.txt_year);
}
public void setMovieName(String movieName) {
this.txtMovieName.setText(movieName);
}
public void setDirectorName(String directorName) {
this.txtDirectorName.setText(directorName);
}
public void setYear(String year) {
this.txtYear.setText(year);
}
}

Views and Data Sources. How do they Communicate?

Views and Data sources are different things. They need an interface to communicate with each other. Okay, but like what? Introducing Adapters…Adapter is a just a class which is tasked to act as a bridge between the data source and the view. It works as a iterator and picks one data unit from the data source and shows it into the View using the ViewHolder until all the data units are traversed.

To achieve this, create a new Java class named MovieAdapter.java and write the following code in it.

public class MovieAdapter extends RecyclerView.Adapter<MovieViewHolder> {    private Context context;
private ArrayList<Movie> movieList;
...
...
}

The Adapter class has two members — namely movieList which will contain the data that needs to be loaded in the view and context which is the context of the Activity that uses the adapter object.

    @NonNull
@Override
public MovieViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.row_movie, parent, false);
return new MovieViewHolder(view);
}

When the ViewHolder is created for the first time, that is when the data is ready to be loaded in the view, onCreateViewHolder callback method of adapter class is called. As you can see, it returns a ViewHolder instance — which in our case is MovieViewHolder. This method binds the row layout file to the with a view object object which is then used to initialise a ViewHolder instance.

    @Override
public int getItemCount() {
return movieList == null ? 0 : movieList.size();
}

This callback method is used by adapter class to determine the no of items in the list, hence the name.

    @Override
public void onBindViewHolder(@NonNull MovieViewHolder holder, int position) {
Movie movie = movieList.get(position);
holder.setDirectorName(movie.getDirectorName());
holder.setMovieName(movie.getName());
holder.setYear(movie.getYear());
}

Here we are. onBindViewHolder is another adaper callback method. This method is called iteratively for every object in the list and we need to define here what to do with our data. In our example, we just want to set some texts to some text fields.

Now, this is what our Adapter class looks like.

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.cradle.recyclerviewexample.R;
import com.cradle.recyclerviewexample.model.Movie;
import com.cradle.recyclerviewexample.ui.MovieViewHolder;
import java.util.ArrayList;public class MovieAdapter extends RecyclerView.Adapter<MovieViewHolder> { private Context context;
private ArrayList<Movie> movieList;
public MovieAdapter(Context context, ArrayList<Movie> movieList) {
this.context = context;
this.movieList = movieList;
}
@NonNull
@Override
public MovieViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.row_movie, parent, false);
return new MovieViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MovieViewHolder holder, int position) {
Movie movie = movieList.get(position);
holder.setDirectorName(movie.getDirectorName());
holder.setMovieName(movie.getName());
holder.setYear(movie.getYear());
}
@Override
public int getItemCount() {
return movieList == null ? 0 : movieList.size();
}
}

Now, we are all set to move on to the MainActivity class to generate and populate data into the RecyclerView.

Ah Finally! Driving code

public class MainActivity extends AppCompatActivity {    private ArrayList<Movie> movieList;    private RecyclerView rvMovies;
...
...
}

MainActivity class has two members — movieList which we want to hold the list of movie objects and rvMovies which is just an object of RecyclerView type (used to handle operations on RecyclerView).

private void init() {
movieList = new ArrayList<>();
rvMovies = findViewById(R.id.rv_movies);
}

This method initialises the class members movieList and rvMovies with their a new ArrayList and RecyclerView respectively.

private void generateData() {
movieList.add(new Movie("Inception", "Christopher Nolan", "2010"));
movieList.add(new Movie("The Social Network", "David Fincher", "2010"));
movieList.add(new Movie("Mad Max: Fury Road", "George Miller", "2015"));
movieList.add(new Movie("12 Years a Slave", "Steve McQueen", "2013"));
movieList.add(new Movie("Whiplash", "Damien Chazelle", "2014"));
movieList.add(new Movie("Prisoners", "Denis Villeneuve", "2013"));
movieList.add(new Movie("Arrival", "Denis Villeneuve", "2016"));
movieList.add(new Movie("Django Unchained", "Quentin Tarantino", "2012"));
}

In this method we added some sample movies data to the movieList which we’ll use shortly in our adapter.

private void setData() {
rvMovies.setLayoutManager(new LinearLayoutManager(this));
rvMovies.setAdapter(new MovieAdapter(this, movieList));
}

In this method we set a LayoutManager for RecyclerView. Now, wait what? LayoutManager is used in the RecyclerView to position items accordingly. Specifically, LinearLayoutManager sets items linearly — horizontal or vertical, latter being the default, GridLayoutManager sets items in a grid like view and StaggeredGridLayoutManager sets items in a staggered grid like view.

In our example, we used LinearLayoutManager because we want to display list in linearly and this layout manager has vertical view as default.

Now, finally MainActivity should look like this.

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;import com.cradle.recyclerviewexample.R;
import com.cradle.recyclerviewexample.adapter.MovieAdapter;
import com.cradle.recyclerviewexample.model.Movie;
import java.util.ArrayList;public class MainActivity extends AppCompatActivity { private ArrayList<Movie> movieList; private RecyclerView rvMovies; private static final String TAG = "MainActivity"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
generateData();
setData();
}
private void init() {
movieList = new ArrayList<>();
rvMovies = findViewById(R.id.rv_movies);
}
private void generateData() {
movieList.add(new Movie("Inception", "Christopher Nolan", "2010"));
movieList.add(new Movie("The Social Network", "David Fincher", "2010"));
movieList.add(new Movie("Mad Max: Fury Road", "George Miller", "2015"));
movieList.add(new Movie("12 Years a Slave", "Steve McQueen", "2013"));
movieList.add(new Movie("Whiplash", "Damien Chazelle", "2014"));
movieList.add(new Movie("Prisoners", "Denis Villeneuve", "2013"));
movieList.add(new Movie("Arrival", "Denis Villeneuve", "2016"));
movieList.add(new Movie("Django Unchained", "Quentin Tarantino", "2012"));
}
private void setData() {
rvMovies.setLayoutManager(new LinearLayoutManager(this));
rvMovies.setAdapter(new MovieAdapter(this, movieList));
}
}

Tired already? Relax, that’s all for it. You can now run the app and the result should be something like the video below.

If you have any query regarding this article or what are the upcoming articles, don’t feel lazy to comment that below. I’ll try my best to stick around.

Part 2 in this series will be coming soon in which we will learn how do they load data in JSON form from something called API and populate that data into RecyclerView along with some bonuses. Meanwhile stay connected.

--

--

Rohit Rawat

A frontend developer proficient in Android, React.js and with a 2 years of industry experience in Android.