Create a List in Android using RecyclerView — Part 1
Welcome to the first article in ‘Create List in Android using RecyclerView’ Series.
Introduction, some boring stuff
RecyclerView
is an AndroidViewGroup
by definition, meaning it is designed to contain other Android views likeButton
,TextView
,EditText
etc. It is basically used to implement lists and grid in Android. AlthoughListView
andGridView
are already there butRecyclerView
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.
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.
Add the following line in the dependency section of the file.
implementation ‘androidx.recyclerview:recyclerview:1.1.0’
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 aModel
, aView
and aController
of these two. In simple words,Model
contains data,View
is where the data is loaded andController
the transactions betweenModel
andView
. 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
.
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 theRecyclerView
.
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.