Lists are inevitable. Your Facebook feed is a list, the music player you use makes use of lists to show tracks on your phone, and even the home screen menu you see on your phone is a list. Lists are considered the most convenient way of displaying data on a small handheld device like a smartphone and why not. After all, they make displaying a huge set of data to users with small windows (device displays) a hassle-free task.

While lists are great at displaying a series of similar looking data, they may not be so good at resource consumption because you see a list needs to create newer view items every time a scroll happens and view creation is an expensive task to be performed. A heavy list means a more resource hungry application and even with paging, lists generally make application suffer performance wise. It was a problem on Android for several years as well before RecyclerView came out.

Google released RecyclerView alongside CardView and Design Support Library in 2014 with the launch of Android Lollipop. The idea behind RecyclerView was simple -- instead of creating views every time user scrolls, create views once and recycle and reuse them if need be. RecyclerView, other than the reuse pattern or ViewHolder pattern (we will see why), offers some other improvements over older listview as well like Layout Manager, Item Decoration, Item Animator and more. Let's dive into the topic and see what RecyclerView offers and why one should use it instead of simpler ListView.

1. What is RecyclerView?

RecyclerView is a list drawing library that essentially provides a fixed-size window to load a large dataset into. It recycles the views it created at the begining when the views go out of scope (window) and then if there is a need, reuses them to make it seem as if the views were never offloaded and were virtually present outside the window. See the three windows below? All three are having a RecyclerView in them. The first makes use StaggeredLayoutManager, while the second and the third make use of LinearLayoutManger. We will see what Layout Managers are later.


You might also notice in the first window that the views are not similar -- they have different data items inside them. Well, that's made possible by RecyclerView, more specifically, RecyclerView's ViewHolder pattern. Declare a separate ViewHolder for each view and let RecyclerAdapter handle the data for indices. We will see how in a while. 

As made clear in the beginning, RecyclerView is a standalone support library that Google's Android team released way back in 2014. So, we need to add it separetely to incorporate it in our application, it doesn't come with any specific SDK tools version. Adding the following in our application's build.gradle's (Module:app) dependencies block and doing a gradle sync will allow us to use the library,

implementation 'com.android.support:recyclerview-v7:26.1.0'

For Android Studio below version 3.0, this needs to be added instead,

compile 'com.android.support:recyclerview-v7:26.1.0' 

2. How is it different from ListView?

RecyclerView can easily be called the better ListView. It works just like a ListView --displays a set of data on the screen but uses a different approach for the purpose. RecyclerView as its name suggests recycles Views once they get out of scope (screen) with the help of ViewHolder pattern. Sure, ListView can also have ViewHolders but that's not available by default forcing us to add more code to improve list performance. On the other hand, ViewHolders are an important part of the whole RecyclerView architecture i.e. the system forces you to have a ViewHolder for any layout you may include. The architecture then uses these ViewHolders to create a View copy of the layout to be used, and instead of recreating them, uses the cached views instead and binds them with new data.

The other benefits that RecyclerView provides over ListView include Layout Manager, Item Decoration and Item Animator. Just think of creating a grid list that has 3 columns, that animates when the a new item is inserted or has proper spacing on all sides of the child view with borders. Seems complicated? Well, RecyclerView makes doing that very easy with these three core features we just talked about. Do this

GridLayoutManager glm = new GridLayoutManager(context, 3);
recyclerView.setLayoutManager(glm);

and we are done making our RecyclerView behave like a grid or this

RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator(); 
recyclerView.setItemAnimator(itemAnimator);

to add simple animations for entry and exit of child views.

3. Definition and attributes

A RecyclerView is nothing but a simple ViewGroup that implements ScrollView. What makes RecyclerView magical is its ability to handle the Views inside it. 

RecyclerView handles a View by marking it either recycled or scraped. A recycled view is the view that has already been inflated and can be put in the cache for later reuse with or without new data binding. A scrap view on the other hand is the view that was detached from the layout at the time of creating, or rather a view that didn't become dirty during previous use. Think of it as a static view. Now, if there is a need for it, RecyclerView will use it with or without data binding. The benefit that a scrap view offers is that we can have a view in the system but there isn't any performance overhead with it when it's not being used.

The basic attributes of RecyclerView are same as any other ViewGroup (remember, it's a ViewGroup?). The special attributes that come with it include reverseLayout, fastScrollingEnabled, layoutManager, spanCount and stackFromEnd. All of these attributes are self-explanatory.

4. What is Layout Manager?

A layout manager is the heart and soul of a RecyclerView. It is responsible for letting the RecyclerView know when to recycle a child view once it's gone out of scope. Without it, RecyclerView can't figure out what kind of layout it is supposed to lay out on the screen, will it be a linear layout or will there be a grid with spans or better will this grid layout be a staggered layout that doesn't respect the idea of keeping views in a row at the same height. The basic idea behind LayoutManager was to make it possible to dynamically change the layout of the same dataset with just an applicaton of a setter.

There are 3 Layout Managers available for RecyclerView:

# LinearLayoutManager: for handling fairly simpler linear layouts (Vertical or Horizontal)

# GridLayoutManager: for making/handling grid layouts with spans (columns)

# StaggeredLayoutManager: for handling staggered layouts like in the screenshot above (1st window)

We will talk more about LayoutManagers in some other post on these only.

5. Recycler Adapter

The most important part of the whole RecyclerView architecture. A RecyclerView adapter just like any other adapter has the responsibility to bind datasets to Views that will be displayed in the window. A general adapter, essentially, is just an iterator that gets its limit from getCount() that generally depends on the size of the dataset and creates new views and binds data to them from that very dataset. ListView or ViewPager uses this kind of adapter. RecyclerView on the other hand uses a more complex system to bind data and handle views.

As we talked above, RecyclerView makes use of ViewHolders by default. So, the Recycler Adapter instead of creating Views, creates ViewHolders that hold the inflated views. Once created the ViewHolder is put in the cache and can be reused if required.

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
   // return new ViewHolder reference here based on the viewType
}

One thing that we need to keep in mind is that ViewHolders are created/referenced based on the itemview type, not on position so there are added benefits with it like it is easier for the adapter to look for views to reuse and we can add add as many heterogeneous views to our RecyclerView by providing new view types.

When working with a RecyclerView Adapter, we need to know these 4 terminologies,

# ItemViewType: a viewType based on position for reuse/recycle of views.

# ViewHolder:  the parent class that handles layout inflation and child view use. onCreateViewHolder (the code above) handles ViewHolder creation/recycle and view inflation based on itemViewType returned by getItemViewType(...).

# Bind ViewHolder: binds data to the child views of the ViewHolder. The public method onBindViewHolder(...) is responsible for binding viewholders,

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int pos) {
   if (holder instanceof MyViewHolder1) {
      // bind data to the views of MyViewHolder1
   }
}

This is the most expensive block of code in the whole adapter since it will called everytime a view has to appear on the screen and thus special care has to be taken to ensure performance. One of those special measures is not adding slow code inside it, like interfaces (onClick events, for example), they belong in the ViewHolder instead.

# Count: the method that will be called several times to know the size limit of the list. It generally returns the size of the dataset used for the adapter.

@Override
public int getItemCount() {
   if (dataset == null)
       return 0;
   return dataset.size();
}

6. Dynamically changing data (notify)

This actually isn't any standalone feature of RecyclerView, instead it is done by the RecyclerView.Adapter as done by any other adapter used for displaying lists.

When querying for more data or updating/removing already present data, we need to notify the adapter that our dataset has changed/updated. There are several methods available with RecyclerView.Adapter to notify it of changes like notifyDataSetChanged() or notifyItemInserted(...) or notifyItemRangeChanged(...). We will see more of this notify feature of adapter in some other post.

7. What now?

We just got to know about RecyclerView, and how it can easily be called the better ListView. We also got to know the key differences between ListView and RecyclerView and how RecyclerView excels at performance by recycling ViewHolders. Also, we now know the need of layout managers and how they can be used to change the look of the recycler layout as well as how adapter works internally to recycle, reuse views and bind data as per the view type.

However, it should be noted that with more features, complexity increases. The same is true with RecyclerView. We get a host of cool features that improve the performance but that means we have to write more code, include more logic in the system. Take the example of header in listview, how simple it is to add a header in listview, but with RecyclerView we have to go an extra mile. We need to add new layout and a new ViewHolder and then a view type that provides reference to this ViewHolder and then bind data for the ViewHolder. This is much more than what we do in ListView. Also, the whole system is pretty complex as compared to a ListView implementation and thus more memory consuming.

We need to note that even though RecyclerView is great, it is not meant for every use case out there. When there is a small dataset that doesn't change much, a ListView can be used for displaying list due to the fact that ListViews are simpler to implement and are less resource consuming. RecyclerViews are meant for bigger, more versatile lists that have different view types and user needs to scroll a lot.

We will see more about the core RecyclerView architecture in future posts. Please be sure to subscribe to our weekly newsletter, follow us on Facebook, Twitter and Google Plus. And yes, if you liked what you just read (you did, right?), please spread love by sharing it among your peers.