RecyclerView in Android: The basics

Google I/O this week brought a lot of exciting news about Android, and we probably need quite some time to get used to what Android L is bringing.

I’ve been playing with RecyclerView these days, and will give you a little presentation of what I discovered so far.

RecyclerView: What it is?

The RecyclerView is a new ViewGroup that is prepared to render any adapter-based view in a similar way. It is supossed to be the successor of ListView and GridView, and it can be found in the latest support-v7 version.

The RecyclerView has been developed with extensibility in mind, so it is possible to create any kind of layout you can think of, but not without a little pain-in-the-ass dose. This is Android, so things are never easy.

If you want to use a RecyclerView, you will need to feel comfortable with three elements:
– RecyclerView.Adapter
– LayoutManager
– ItemAnimator

RecyclerView.Adapter

RecyclerView includes a new kind of adapter. It’s a similar approach to the ones you already used, but with some peculiarities, such as a required ViewHolder. You will have to override two main methods: one to inflate the view and its view holder, and another one to bind data to the view. The good thing about this is that first method is called only when we really need to create a new view. No need to check if it’s being recycled.

[java]
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter.ViewHolder> {

private List<ViewModel> items;
private int itemLayout;

public MyRecyclerAdapter(List<ViewModel> items, int itemLayout) {
this.items = items;
this.itemLayout = itemLayout;
}

@Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(itemLayout, parent, false);
return new ViewHolder(v);
}

@Override public void onBindViewHolder(ViewHolder holder, int position) {
ViewModel item = items.get(position);
holder.text.setText(item.getText());
holder.image.setImageBitmap(null);
Picasso.with(holder.image.getContext()).cancelRequest(holder.image);
Picasso.with(holder.image.getContext()).load(item.getImage()).into(holder.image);
holder.itemView.setTag(item);
}

@Override public int getItemCount() {
return items.size();
}

public static class ViewHolder extends RecyclerView.ViewHolder {
public ImageView image;
public TextView text;

public ViewHolder(View itemView) {
super(itemView);
image = (ImageView) itemView.findViewById(R.id.image);
text = (TextView) itemView.findViewById(R.id.text);
}
}
}
[/java]

That’s a simple Adapter. But things start to get complicated. There isn’t (or a least I didn’t found) a onItemClickListener on RecyclerView. So the adapter will be a good candidate to handle the events.

If you want to add or remove items from the adapter, you will need to explicitly inform to the adapter. That’s a bit different from the former notifyDataSetChanged():

[java]
public void add(ViewModel item, int position) {
items.add(position, item);
notifyItemInserted(position);
}

public void remove(ViewModel item) {
int position = items.indexOf(item);
items.remove(position);
notifyItemRemoved(position);
}
[/java]

LayoutManager

This is the class that will decide in which part of the screen the views are placed. But that’s only one of its many responsibilities. It must be able to manage scrolling and recycling among others.

There’s only one implemented class of this LayoutManager. It’s called LinearLayoutManager, and it is above 1500 lines of code, only for you to understand the complexity. This manager is able to simulate a ListView (both vertical and horizontal), without headers or footers.

Subclassing LayoutManager is not for rookies at all, and we will have to rely on community to achieve RecyclerView full potential. Along with the example, I will be uploading in short time an implementation for GridView.

I think the key behind this is to create a BaseLayoutManager from LinearLayoutManager code and extend it from here. Probably the final version of support-v7 will come with more and better implementations.

ItemAnimator

ItemAnimator will animate ViewGroup modifications that are notified to adapter. Basically it will automatically animate adding and removing items. That’s not an easy class either, and we find a DefaultItemAnimator that works quite well.

RecyclerView setup

So, in the end, if you want to initialize a working RecyclerView, you will need to do something like this:

[java]
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(new MyRecyclerAdapter(createMockList(), R.layout.item));
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setItemAnimator(new DefaultItemAnimator());
[/java]

setHasFixedSize() is used to let the RecyclerView that its size will keep the same. This information will be used to optimize itself.

Conclusion

RecyclerView is indeed a powerful view, and its limits will be more in the part of the developer that the view itself. The learning curve may be hard, but I’m sure that Android community will soon release awesome implementations of LayoutManager.

I’m creating a github repository, where you can find this example. It will serve as the basis for an extension library I’m planning to create. You will be able to test a GridView implementation. Any feedback will be welcomed.

RecyclerViewExtensions on Github

RecyclerView example

55 thoughts on “RecyclerView in Android: The basics”

    1. Antonio Leiva

      You already can download the code from Github. Only Android-L compatible however.

      1. typical android; create another slightly similar, but yet different and without any real benefit thing to solve a non problem we already have several solutions for. Not that it impacts the quality of this great write up; thanks for the info.

    2. I think Designing RecyclerView was 1 of major steps towards handling everything from system side & let user write minimum code (as compared to extending traditional BaseAdapter), I have built libarary which eases out the Multi-Row-Type support for list-view, could you look into it & provide your feedbacks that how can I take my lib towards more usefullness.
      https://github.com/birajpatel/EasyListViewAdapters

    1. Antonio Leiva

      Not at the moment, until Google reduces its minSdk on new support libraries. I can imagine you can always copy all class sources into your project, but it’s not recommended to use them on production because it may have big changes and won’t work anymore.

      1. Set your compile SDK to 19
        Set your minsdk to 15
        Set your target SDK to 19
        Add these to the dependencies
        compile ‘com.android.support:cardview-v7:+’
        compile ‘com.android.support:recyclerview-v7:+’
        compile ‘com.android.support:palette-v7:+’

        Add this line to your android manifest.xml inside the manifest tag

        I’m excited to see what the grid view looks like. I hope it scrolls both horizontally and vertically!

  1. i found that on a Reddit post. In AndroidManifest.xml. on manifest tag add that xmlns:tools=”http://schemas.android.com/tools”
    then you can use the new feature added in the new Android studio.

    By doing that you tell the manifest merger that is able to replace the minsdk

  2. Hi, glad to know someone is also trying out this new stuff so soon. Did you get your data set changes to work properly for your adapter? I have tried notifyItemInserted, notifyItemRangeInserted and notifyDataSetChanged and none of them seem to work.

    1. Antonio Leiva

      I only tried notifyItemInserted and notifyItemDeleted, and both worked. But you also have to remove the items from your list. Check the example linked in this post, I’m deleting the items when clicked.

  3. Hi, You mentioned that DefaultItemAnimator works quite well.
    Can you elaborate more ? ‘Cause I tried the code on emulator and when i use notifyItemInserted(position), the list doesn’t refresh automatically. I need to scroll up & down to see the new item. When I use notifyItemInserted(position), i can see the new item automatically. But, there is no auto animation. Thanks in advance.

    1. Antonio Leiva

      Check the example at Github from this article, maybe there’s something you are missing.

    1. Antonio Leiva

      Yes, there are some known unsolved issues at that example. I accept pull requests if you find some time to find a solution.

  4. Thanks for a very nice article… I am trying RecyclerView as a Section Header List or Sticky header list,Do you have any idea how can I achive this..

    1. Antonio Leiva

      Not an easy way. You would need to create your own implementation of LayoutManager. I think the use of LayoutManager is too difficult right now and that we will se big changes in final release. Or, at least a few more standard layouts rather than LinearLayoutManager.

  5. Hi your Blog was awesome! I like to have different types of views for each row in the list ( heterogeneous list), in that case how I best make use of recyclerView.. Earlier I was achieving using List view getViewTypeCount() and getItemViewType(). Can you put some some light on this ?

  6. ViewPager make removing view real pain , what about recycleview replace viewpager , does it got better support with dynamically add and remove views? and also visuality could recycleview replace viewpager?

  7. OK, finally it works even on Kitkat, using the most updated SDK and support library.
    I have a question though:
    How should it handle filters? should it work by implementing Filterable, just as before, or does it have a new way of doing it ?

  8. Hey AntonioLeivaGordillo thank you for the nice article but i have problem when deleting views quickly my app crashes and i get this error
    java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 0(offset:-1).state:2
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3300)
    at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:3258)
    at wappi.AfricanFashion.BaseLayoutManager$RenderState.next(BaseLayoutManager.java:1330)
    at wappi.AfricanFashion.GridLayoutManager.fill(GridLayoutManager.java:55)
    at wappi.AfricanFashion.BaseLayoutManager.scrollBy(BaseLayoutManager.java:840)
    at wappi.AfricanFashion.BaseLayoutManager.fixLayoutEndGap(BaseLayoutManager.java:616)
    at wappi.AfricanFashion.BaseLayoutManager.onLayoutChildren(BaseLayoutManager.java:544).

    But it doesn’t happen when i delete items slowly any ideas .

    1. Yeah, that was a bug in my code but I can’t remember why. Don’t use those layouts anyway, there is a GridLayoutManager in final SDK. The code on that repository is only thought as a didactic example, not prepared for production code at all.

      1. Hey, you said there’s a GridLayoutMangere in the final SDK? What do you mean? I’m targeting SDK 21, and using the recyclerview support library v21, but Android Studio still won’t resolve GridLayoutManager. What am I doing wrong?

      2. I am using recyclerview in my app but it is not appearing in all versions except in lollipop (nexus 5 with 5.0.1). How can I solve this? I have tried in jellybeans and kitkat… in sdk manager all is updated.

  9. I Found a little BUG, When the Items size/length is even (20,18,16)….. if i click last 4 item it will error. and give indexOutOfBound the REST is FIne…. Something error in BaseLayoutManager… 🙁

  10. endless RecyclerView with progress bar at bottom while loading more data from service ?

  11. On filter of recyclerview using same adapter how to set on item click listener to that item get appropriate information

  12. hi.
    I am new in android programming and in wanna use a edittext to search in recycleview. i mean write a filter but i don’t now how?

  13. Hello Sir,
    Sorry for my bad English. I wanna ask about recyclerview.
    I have 10 items in my recyclerview, then I wanna remove item 0,1,2
    like this example :

    for(Integer i = 0; i<3; i++){
    list.remove(i);
    adapter.notifyItemRemoved(i);
    adapter.notifyItemRangeChanged(i, list.size());
    }

    then the result I have :
    1,3,5,6,7,8,9,10
    item 1 not deleted, but my item 4 been deleted.

    Can you help me Sir…

    Best Regards,

    Zigic

Comments are closed.