Grokking Android

Getting Down to the Nitty Gritty of Android Development

A First Glance at Android’s RecyclerView

By 56 Comments

At this year’s Google I/O, Google released a preview to the upcoming Android version. The so called L Developer Preview. This is a very big improvement over previous releases and I really love that Google is doing this. I think we all benefit by this decision. As developers and as consumers alike!

Part of this preview are two new views: RecyclerView and CardView. This post gives you an introduction to the RecyclerView, it’s many internal classes and interfaces, how they interact and how you can use them.

Let me start with the good news: RecyclerView is part of the support library. So you can use it right now. Ok: You can use it as soon as the final support lib accompanying the L release gets released. So better to familiarize yourself with it right away 🙂

Sample project

The screenshots and the video at the end of the post show the sample project for this post in action. You can find the source of this sample at github. Keep in mind that the RecyclerView API is not yet finalized. Google might still change things that could break the sample when they release the final version of Android L.

What’s with this odd name? Why RecyclerView?

This is how Google describes RecyclerView in the API documentation of the L preview release:

A flexible view for providing a limited window into a large data set.

So RecyclerView is the appropriate view to use when you have multiple items of the same type and it’s very likely that your user’s device cannot present all of those items at once. Possible examples are contacts, customers, audio files and so on. The user has to scroll up and down to see more items and that’s when the recycling and reuse comes into play. As soon as a user scrolls a currently visible item out of view, this item’s view can be recycled and reused whenever a new item comes into view.

The following screenshots of the sample app illustrate this. On the left is the sample app after the initial start. When you scroll the view up, some views become eligible for recycling. The red area on the right screenshot, for example, highlights two invisible views. The recycler can now put these views into a list of candidates to be reused should a new view be necessary.

These two screens show what recycling means. On the right two views are eligible for reuse
These two screens show what recycling means. On the right two views are eligible for reuse

Recycling of views is a very useful approach. It saves CPU resources in that you do not have to inflate new views all the time and it saves memory in that it doesn’t keep plenty of invisible views around.

Now, you might say: That’s nothing new. And you’re right! We had that with ListView for a very long time. The concept of recycling views itself it not new. But while you previously had a ListView where the appearance, recycling and everything was tightly coupled, Google now follows a much better, a much more flexible approach with the new RecyclerView. I really like the approach Google has taken here!

RecyclerView doesn’t care about visuals

Here’s the thing: While with Listview we had tight coupling, Google now uses an approach where the RecyclerView itself doesn’t care about visuals at all. It doesn’t care about placing the elements at the right place, it doesn’t care about separating any items and not about the look of each individual item either. To exaggerate a bit: All RecyclerView does, is recycle stuff. Hence the name.

Anything that has to do with layout, drawing and so on, that is anything that has to do with how your data set is presented, is delegated to pluggable classes. That makes the new RecyclerView API extremely flexible. You want another layout? Plug in another LayoutManager. You want different animations? Plug in an ItemAnimator. And so on.

Here’s the list of the most important classes that RecyclerView makes use of to present the data. All these classes are inner classes of the RecyclerView:

The most important classes of the RecyclerView API
Class Usage
Adapter Wraps the data set and creates views for individual items
ViewHolder Holds all sub views that depend on the current item’s data
LayoutManager Places items within the available area
ItemDecoration Draws decorations around or on top of each item’s view
ItemAnimator Animates items when they are added, removed or reordered

In the next paragraphs I will briefly describe what each class or interface is about and how RecyclerView uses it. In future posts I will revisit some of these classes, write about them in detail and show you how to customize them for your project’s needs.

ViewHolder

ViewHolders are basically caches of your View objects. The Android team has been recommending using the ViewHolder pattern for a very long time, but they never actually enforced the use of it. Now with the new Adapter you finally have to use this pattern.

It’s a bit weird that Google waited so long to enforce the usage of the ViewHolder pattern, but better late than never. If you do not know about the ViewHolder pattern, have a look at this Android training session. It uses the old Adapter, but the pattern itself hasn’t changed.

Also searching for ViewHolder should yield plenty of hits to further blog posts. For example this post by Antoine Merle about ListView optimizations.

One thing that is specific to any RecyclerView.ViewHolder subclass is that you can always access the root view of your ViewHolder by accessing the public member itemView. So there’s no need to store that within your ViewHolder subclass.

And should you decide to override toString() have a look at the base class. Its toString() implementation prints some useful information you should consider to use for your log messages as well.

Here’s the code for the ViewHolder of the sample project. The ViewHolder is an inner class of the sample project’s Adapter:


public final static class ListItemViewHolder extends RecyclerView.ViewHolder {
TextView label;
TextView dateTime;

public ListItemViewHolder(View itemView) {
super(itemView);
label = (TextView) itemView.findViewById(R.id.txt_label_item);
dateTime = (TextView) itemView.findViewById(R.id.txt_date_time);
}
}

RecyclerView.Adapter

Adapters fulfill two roles: They provide access to the underlying data set and they are responsible for creating the correct layout for individual items. Adapters always were part of Android and were used in many places. ListView, AutoCompleteTextView, Spinner and more all made use of adapters. All those classes inherit from AdapterView. But not so RecyclerView.

For the new RecyclerView Google has decided to replace the old Adapter interface with a new RecyclerView.Adapter base class. So say good bye to things like SimpleCursorAdapter, ArrayAdapter and the like. At least in their current incarnation.

Currently there is no default implementation of RecyclerView.Adapter available. Google might add some later on, but I wouldn’t bet on this. For Animations to work properly, cursors and arrays aren’t the best fit, so porting the current Adapter implementations might not make too much sense.

Since RecyclerView.Adapter is abstract you will have to implement these three methods:

The VH in the method signatures above is the generic type parameter. You specify the concrete type to use when you subclass the RecyclerView.Adapter. You can see this in line 3 of the next code sample.

The most basic adapter for the sample layout looks like this:


public class RecyclerViewDemoAdapter extends
RecyclerView.Adapter
<RecyclerViewDemoAdapter.ListItemViewHolder> {

private List<DemoModel> items;

RecyclerViewDemoAdapter(List<DemoModel> modelData) {
if (modelData == null) {
throw new IllegalArgumentException(
"modelData must not be null");
}
this.items = modelData;
}

@Override
public ListItemViewHolder onCreateViewHolder(
ViewGroup viewGroup, int viewType) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.item_demo_01,
viewGroup,
false);
return new ListItemViewHolder(itemView);
}

@Override
public void onBindViewHolder(
ListItemViewHolder viewHolder, int position) {
DemoModel model = items.get(position);
viewHolder.label.setText(model.label);
String dateStr = DateUtils.formatDateTime(
viewHolder.label.getContext(),
model.dateTime.getTime(),
DateUtils.FORMAT_ABBREV_ALL);
viewHolder.dateTime.setText(dateStr);
}

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

public final static class ListItemViewHolder
extends RecyclerView.ViewHolder {
// … shown above in the ViewHolder section
}
}

RecyclerView.LayoutManager

The LayoutManager is probably the most interesting part of the RecyclerView. This class is responsible for the layout of all child views. There is one default implementation available: LinearLayoutManager which you can use for vertical as well as horizontal lists.

You have to set a LayoutManager for your RecyclerView otherwise you will see an exception at Runtime:


08-01 05:00:00.000 2453 2453 E AndroidRuntime: java.lang.NullPointerException: Attempt to invoke virtual method ‘void android.support.v7.widget.RecyclerView$LayoutManager.onMeasure(android.support.v7.widget.RecyclerView$Recycler, android.support.v7.widget.RecyclerView$State, int, int)’ on a null object reference
08-01 05:00:00.000 2453 2453 E AndroidRuntime: at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:1310)

Only one method of LayoutManager is currently abstract:

But there is another one where the code states that you should overrride it since it’s soon going to be abstract:


public void scrollToPosition(int position) {
if (DEBUG) {
Log.e(TAG, "You MUST implement scrollToPosition. It will soon become abstract");
}
}

That’s very weird! Why not make it abstract right away? Anyway: Better you override this one to be on the safe side for when Google releases the final version of L.

But only overriding those two methods won’t get you very far. After all the LayoutManager is responsible for positioning the items you want to display. Thus you have to override onLayoutChildren() as well.

This method also contains a log statement stating “You must override onLayoutChildren(Recycler recycler, State state)”. Ok, then make it abstract 🙂 Luckily there’s still plenty (?) of time to change that into a proper abstract method for the final release of L. We all make mistakes. After all, my “Stupid stuff devs make” series is all about blunders that I made. So don’t get me wrong. No hard feelings here!

LinearlayoutManager

The LinearLayoutManager is currently the only default implementation of LayoutManager. You can use this class to create either vertical or horizontal lists.

The implementation of LinearLayoutManager is rather complex and I only had a look at some key aspects. I will return to this implementation in my post about custom LayoutManagers.

To use the LinearLayoutManager you simply have to instantiate it, tell it which orientation to use and you are done:


LinearLayoutManager layoutManager = new LinearLayoutManager(context);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.scrollToPosition(currPos);
recyclerView.setLayoutManager(layoutManager);

LinearLayoutManager also offers some methods to find out about the first and last items currently on screen:

Surprisingly these methods are not part of the source code in the SDK folder, but you can use them as they are part of the binaries. As I cannot imagine those being removed, I’m sure you’ll find these in the final L release as well.

Other methods help you get the orientation of the layout or the current scroll state. Others will compute the scroll offset. And finally you can reverse the ordering of the items.

Since I’m going to write an extra post about LayoutManagers this should suffice for now.

RecyclerView.ItemDecoration

With an ItemDecoration you can add an offset to each item and modify the item so that items are separated from each other, highlighted or, well, decorated.

You do not have to use an ItemDecoration. If, for example, you use a CardView for each item, there’s no need for an ItemDecoration.

On the other hand you can add as many ItemDecorations as you like. The RecyclerView simply iterates over all ItemDecorations and calls the respective drawing methods for each of them in the order of the decoration chain.

The abstract base class contains these three methods:

Anything you paint in onDraw() might be hidden by the content of the item views but anything that you paint in onDrawOver() is drawn on top of the items. If you simply create a bigger offset and, for example, use this offset to paint dividers, this of course is of no importance. But if you really want to add decorations, you have to use onDrawOver().

The LayoutManager calls the getItemOffset() method during the measurement phase to calculate the correct size of each item’s views. The outRect parameter might look a bit odd at first. Why not use a return value instead? But it really makes a lot of sense, since this allows RecyclerView to reuse one Rect object for all children and thus save resources. Not necessarily nice — but efficient.

One thing I didn’t expect considering the name of the class is that the onDraw()/onDrawOver() methods are not called for each item, but just once for every draw operation of the RecyclerView. You have to iterate over all child views of the RecyclerView yourself.

I will explain this in more detail in a follow-up post about writing your own ItemDecorations.

RecyclerView.ItemAnimator

The ItemAnimator class helps the RecyclerView with animating individual items. ItemAnimators deal with three events:

Luckily there exists a default implementation aptly named DefaultItemAnimator. If you do not set a custom ItemAnimator, RecyclerView uses an instance of DefaultItemAnimator.

Obviously for animations to work, Android needs to know about changes to the dataset. For this Android needs the support of your adapter. In earlier versions of Android you would call notifyDataSetChanged() whenever changes occured, this is no longer appropriate. This method triggers a complete redraw of all (visible) children at once without any animation. To see animations you have to use more specific methods.

The RecyclerView.Adapter class contains plenty of notifyXyz() methods. The two most specific are:

The following video shows the result of an addition as well as a removal of an item in the sample app:

A short video showing the default animations for the removal and addition of elements

Listeners

RecyclerView also offers some rather generic listeners. Once again you can safely forget everything you used to use up to now. There is no OnItemClickListener or OnItemLongClickListener. But you can use an RecyclerView.OnItemTouchListener in combination with gesture detection to identify those events. A bit more work and more code to achieve the same result. I still hope for Google to add those Listeners in the final release. But whether those Listeners will be added is as an open question.

Combining all classes

You combine the classes either in a fragment or an activity. For the sake of simplicity my sample app uses activities only.

First of all here’s the layout file containing the RecyclerView:


<RelativeLayout 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"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".RecyclerViewDemoActivity">

<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:listitem="@layout/item_demo_01"
/>

<ImageButton
android:id="@+id/fab_add"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_width="@dimen/fab_size"
android:layout_height="@dimen/fab_size"
android:layout_gravity="bottom|right"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
android:background="@drawable/ripple"
android:stateListAnimator="@anim/anim"
android:src="@drawable/ic_action_add"
android:elevation="1dp"
/>
</RelativeLayout>

As you can see, nothing special here. You do not define the orientation or stuff like that on the RecyclerView. Actually RecyclerView itself makes no use of the attributes, it passes them on to the parent (which is ViewGroup) and that’s it.

There is one place within RecyclerView where an AttributeSet is used and that is in the generateLayoutParams() method:


@Override
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
if (mLayout == null) {
throw new IllegalStateException("RecyclerView has no LayoutManager");
}
return mLayout.generateLayoutParams(getContext(), attrs);
}

In this snippet the RecyclerView passes the AttributeSet on to the LayoutManager.

The Java code is also pretty simple:


setContentView(R.layout.activity_recyclerview_demo);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);

LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
layoutManager.scrollToPosition(0);
recyclerView.setLayoutManager(layoutManager);

// allows for optimizations if all item views are of the same size:
recyclerView.setHasFixedSize(true);

// For the sake of simplicity I misused the Application subclass as a DAO
List<DemoModel> items = RecyclerViewDemoApp.getDemoData();
adapter = new RecyclerViewDemoAdapter(items);
recyclerView.setAdapter(adapter);

RecyclerView.ItemDecoration itemDecoration =
new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST);
recyclerView.addItemDecoration(itemDecoration);

// this is the default;
// this call is actually only necessary with custom ItemAnimators
recyclerView.setItemAnimator(new DefaultItemAnimator());

// onClickDetection is done in this Activity’s OnItemTouchListener
// with the help of a GestureDetector;
// Tip by Ian Lake on G+ in a comment to this post:
// https://plus.google.com/+LucasRocha/posts/37U8GWtYxDE
recyclerView.addOnItemTouchListener(this);
gesturedetector =
new GestureDetectorCompat(this, new RecyclerViewDemoOnGestureListener());

Connecting all those elements together roughly consists of these steps:

  1. Get a reference to your RecyclerView
  2. Create a LayoutManager and add it
  3. Create an Adapter and add it
  4. Create zero or more ItemDecorations as needed and add them
  5. Create an ItemAnimator if needed and add it
  6. Create zero or more listeners as needed and add them

All in all about 30 lines of code.

Now of course this is misleading. That’s only the glue code. The really interesting stuff is in RecyclerView's many inner classes which you can subclass and tweak to your needs. That’s where the real work is done.

But the separation of concerns Google created helps you stick to one task within one implementation and it should make reuse easier to achieve. That’s why I like RecyclerView and its ecosystem. I’m not afraid to criticize big G, but that’s well done, Google!

Gradle integration

To use RecyclerView you have to add it to your gradle file. Adding the support library alone is not enough:


dependencies {
//…
compile ‘com.android.support:recyclerview-v7:+’
//…
}

Is that the final API?

Of course I do not know if the concrete implementations that the preview contains will be in the final release of Android L. But I guess so. And I expect some additions as well as minor changes to the API, based on bug reports and developer feedback.

Google itself gives one hint in the current API documentation about more stuff to come. The documentation for the RecyclerView.LayoutManager class contains this nugget:

Several stock layout managers are provided for general use.

So we can expect more LayoutManagers. Which, of course, is good. Furthermore I expect at least one default ItemDecoration as well. After all the support library’s sample project contains a DividerItemDecoration, which works well with the LinearLayoutManager.

I’m more skeptical about adapters. While an ArrayAdapter (or better yet, ListAdapter) is very well possible, I am more doubtful about a CursorAdapter since cursors do not lend themself easily to the new addition and removal notifications within the Adapter.

Lucas Rocha’s TwoWayView to simplify your life

I strongly recommend to have a look at Lucas Rocha’s TwoWayView project. He has updated his project to work with RecyclerView and has done a great deal to make using RecyclerView a lot easier. For many use cases the default layouts he provides should suffice. And he also provides support for custom LayoutManagers. Which are simpler to write using his framework than with the base RecyclerView.

Take a look at his project and check out if it covers all you need. Using it helps you get rid of some of RecyclerView‘s complexity.

For more information about his project see his blog post about how TwoWayView extends and simplifies RecyclerView.

To learn about news about this project follow Lucas Rocha on Google plus or Twitter.

I will cover TwoWayView in this series as well – so stay tuned 🙂

Report bugs!

We currently have a developer preview. The first time Google does this for Android. Really nice. But of course this preview is not free of bugs. To help us all get a more stable final release, give feedback or issue bug reports, if you encounter anything that bothers you or is a bug. There is a special L preview issue tracker.

And that’s it for today

I started this post as part of the preparation for my talk at the July meetup of the Dutch Android User Group.

I had much fun presenting about this topic at the July meetup of the Dutch Android User Group. And I had fun digging into this topic – and still have. Reading the source of RecyclerView and its many inner classes is really interesting. Thanks to the organizers for giving me the opportunity to speak about this topic and for forcing me to dig into this stuff 🙂

At Utrecht I had 15-20 minutes for my talk. How I managed to get it done in time is still a mystery to me. As you can see there’s a lot to talk about – and this post is only the beginning.

Until next time!

Wolfram Rittmeyer lives in Germany and has been developing with Java for many years.

He recently shifted his attention to Android and blogs about anything interesting that came up while developing for Android.

You can find him on Google+ and Twitter.

56 thoughts on “A First Glance at Android’s RecyclerView”

  1. Can this already be used in production code? Since the support lib is bundled with the app changes to it shouldn’t break anything?

    1. Wolfram Rittmeyer

      Even if it’s possible (I haven’t tried), I would not do so. Just start a branch where you use the new stuff and fix bugs when the final L release gets published. The API is bound to change at places where it doesn’t suit effective development.

    2. The source code is bundled with the sdk (just open the recycler*source.jar). You can see that there are various //TODO in the multiple classes of recyclerview.
      Not to mention that some things are entirely absent (no gridlayoutmanager, no headers, …) and we don’t even know if they will be added for the release.
      For gridviews and even more staggered gridviews, I would not use recyclerview before release. Even though there are some communities made libraries to do so, using a preview API with a library that has never been tested on a real life large scale is asking for a disaster.
      For a ListView replacement, if you are writing a new component from scratch that needs some advanced features that recyclerview offers, it might a viable solution if :
      -writing it on top of ListView would need 1000 lines of unmaintanable code that would be very costly to migrate to RecyclerView.
      -you are ready to delve into the full recyclerview code & make the appropriate corrections.

      1. Wolfram Rittmeyer

        Interesting. I only knew of this location within the SDK folder: ./sources/android-20/android/support/v7/widget/

        But since all files in the jar are bigger, those probably are newer. Furthermore they contain the four methods findFirstVisibleItemPosition() and so on that I missed in the sources. Thanks for pointing this out!

  2. Is it me or I cannot find the project demo with this excellent talk? Thanks!

    1. Wolfram Rittmeyer

      You’re right. I’m too knackered to upload it to github today. I will add it tomorrow. Sorry!

      1. No problema at all. I said because it is weird not upload the project =D. Thanks!

      2. Wolfram Rittmeyer

        Forgot about it again. It’s now on github.

  3. Thanks for this article! Really exhaustive!

  4. Can ItemAnimator be used for animating an item’s height (ie expand/collapse an item)?

    1. Wolfram Rittmeyer

      If you want to scale it out of view on removal and scale it into view on addition, then, yes. ItemAnimator is only for animations based on addition, removal or for animations to fill up empty space after removal or to make place before addition. For these situations, though, you should be able to do anything. It’s not useful for anything else.

    2. I have been able to use RecyclerView in conjonction with LayoutTransition in order to make expand animations. It is a bit of a hack though, it will not necessarily work with the release version of RecyclerView.

      I can post the code somewhere if you want, but basically :
      -I have two views types, NORMAL & EXTENDED
      -the onCreateViewHolder method always inflates the same layout. It contains the retracted layout and a ViewStub that I inflate if I need to extend this cell.
      -the model keeps a track of whether the view should be expended or not, that way RecyclerView can reserve the right amount of space during scrolling with onBindViewHolder.
      -on Click on the cell, I activate LayoutTransition.CHANGING on it (and I deactivate it in onBindViewHolder to avoid some glitches), I change the item type to EXTENDED and I pass the visibility of the extended part of the layout from GONE to VISIBLE.

      It is not perfect though, RecyclerView does not always animates the move of the next cells.

      1. Seems like a little bit of a hack though. Does it still work for in production version of RecyclerView??

        1. I explicitely wrote that it is a bit of a hack 🙂 .
          It is a feature of the platform, but it has not been written for scrolling containers.
          I have not tested it with the release version of RV, outside of the technical side it was an awful design and the product team came to its senses and we replaced it.

  5. Can I download the above example somewhere? I’m especially interested in the add-button. How do the drawables for the imagebutton and the background look like? What does the statelistanimator?

    1. Wolfram Rittmeyer

      I’m just resting on other’s shoulders. In this case Gabriele Mariotti’s gist: https://gist.github.com/gabrielemariotti/d1baf785c2444d29819c

    2. Wolfram Rittmeyer

      Yes. It’s on github.

  6. You should try out my version at parchment.mobi . I’d love to hear how they compare.

    1. Wolfram Rittmeyer

      As the author of the parchment library you’re in a much better position to compare both approaches than I am. Especially since my time is too limited to do that.

  7. Thank you, this is a very good first look at this API!

    About your skepticism about the future availability of a CursorAdapter… Well I certainly hope it will happen! It would be very strange if it didn’t. I mean most of the apps I’ve been working on have their list populated with data coming from a ContentProvider, and use CursorLoaders. I really think this should still be possible to do with the new API – and if not, then I would be very surprised, and upset 🙂

    1. Wolfram Rittmeyer

      Benoît, it is of course possible to do a CursorAdapter the same way we did before (more or less at least). The problem is: Will this be enough? Don’t we want proper animations for removing items, changing items and the like? And that’s where I think Loaders and stuff like swapCursor() do not work anymore. From ContentObservers (the basis of Loaders) we do not get the information as to what items have changed. But you need this information to call notifyItemRemoved(), notifiyItemAdded() or notifyItemChanged(). I still do not have a solution for this. The only one I can think of is comparing data sets. But that can be very costly depending on the size of the set.

      It might be more appropriate to use in-app messaging (Otto, EventBus) to propagate dataset changes and to trigger animations.

  8. It’s surprising that ItemDecoration does not have information about current position or viewholder. How to customize ItemDecoration for different item ? say have a rounder color background only for first and last items seems impossible

    1. You have access to the View object (because you have to iterate over all views). With the id of the view, you have all the information you need:

      [java]
      if (view.getId() == R.id.header) {
      view.setBackground(fancyHeaderColor);
      } else {
      view.setBackground(boringItemStatelistDrawable);
      }
      [/java]

  9. How to implement lazyloading in RecyclerView?

  10. Hi Wolfram,

    Your Adapter sample has a mistake in line 23 where you instantiate your ViewHolder – you pass the viewType, but the ViewHolder doesn’t have a parameter for the type.

    The current version of the released RecyclerView (as of writing this comment) will set `mItemViewType` itself after calling the implemented version of `onCreateViewHolder(ViewGroup, int)` (`RecyclerView#createViewHolder(ViewGroup, int)`), which allows you to call `ViewHolder#getItemViewType()`.

    Not sure I like ViewHolder enforcement – we have tended to use the HolderView pattern over the last year (http://www.jayway.com/2013/11/06/viewholder-vs-holderview/) and if we continue to use it, then it just means the ViewHolder is going to be empty. Maybe it’s better to have dumber views, MVP style, but I have grown to like it, and see adv/disadv of each side.

    1. This code was based on the L preview. Haven’t rechecked the sample code afterwards. As soon as I have time, I will do so and release a new version of the sample app and an updated version of this post. For now I’m just going to add a short text pointing to your comment 🙂

      BTW: Thanks!

      I also think the ViewHolder enforcement is odd:

      It’s very late: Why not try to establish this as a needed pattern earlier?
      The community now found interesting alternatives to it – as you mention.

      But I guess Google has a better insight into what goes on in the wild – and probably has chosen to do so because too many didn’t use any proper solution.

      1. Whoa. Stupid response by me 🙂

        Fixed! Obviously I didn’t write both parts of the post as one fluid text but at different states of my project.

  11. Hi, very nice tutorial.
    I have one question, How could I animate selected item and scroll it to center, not clicked or long clicked.
    One way I found is to animate item in “onFocusChangedListner”, and I get position of focused item and then animate it and scroll it to centre, but I don’t think its a proper way of doing this.
    Any suggestions ?

  12. So, the official support library is here yet and Android 5.0 nearly… but I still can’t find how to use RecyclerView with a Cursor? Is there any example, best practice or library?

    1. Sorry, Marcus, but I still haven’t seen anything about this. I’m curious myself how to best solve this issue.

      My current line of thought goes something like this: Any change not done by the user (e.g. caused by new data as a result of a sync): Ignore this is the UI – unless the user reloads the screen (e.g. comes back from another app to revisit where she left off). Any change done by the user: Manually trigger those changes in the adapter to get animations. This basically means to no longer use Loaders. Since I do like them, I’m not sure this is a good proposal 🙂

      That’s what I am going to try for an upcoming app anyway. It indeed doesn’t use Loaders. Not sure, though, how this will work out.

      1. Currently I’m developing a wear app only for private use, so I don’t really care about the animations. But I’m not sure if it is the right way to develop my own CursorAdapter which was part of the SDK ever…

        Also it feels very wrong to not use loaders anymore. And ignoring background updates of data can’t be the right way either…

        1. If you don’t care, why not do it as always – and just call notifiyDatasetChanged() whenever the onLoadFinished() method gets called?

          About ignoring background updates: I suggest to only do so while your ap is currently on the screen. If the user switches the app, goes to the home screen or whatever, any changes should be reflected when the user returns to the app. The user won’t know about any backend changes anyway. If there are frequent changes and the user indeed does expect them, you could show some kind of clickable “New data available. Do you want to refresh this list?” information on the screen.

          1. There ARE cases where background model updates should be reflected in real time in the UI.
            I have no solution yet neither, but ignoring sync or gcm based updates is not the right direction to me.
            As stated in the docs, notifiyDatasetChanged should only be done as a last solution.
            Preferred notifyItem* methods should be used as much as possible, but how can we call those methods from a service (gcm or syncadapter case), which cannot hold a reference to the adapter?
            F.

          2. Might depend on the situation and the amount of data involved. One could use either a LocalBroadcastManager or – IMHO better – an eventbus to propagate data changes.

            You could – say – post an event with a list of ids for all changed elements at the end of a sync. Even better three lists: deletedElements, newElements, changedElements. Than register to listen to these events in your fragment to call the appropriate methods on the adapter. Right now that would be my preferred method. Still not sure about the best way – but that’s my current line of thought for stuff where an immediate reflection of changes is appropriate.

          3. I agree. As a replacement for a Bus, you could insert modifications events in a table (three types of event: insert, delete, update), which your adapter or the fragment registers as an observer (maybe with a good old cursor loader). Once queried and the corresponding notifyItem* method called on the adapter, the table can be flushed (or the event marked as treated).
            I really look forward for an android sample of recyclerview live updating!
            F.

          4. I’ve just created a draft as a reminder to post something about this 🙂 But given my workload that’s not going to happen soon.

  13. I am getting LayoutManager already attached to a recyclerView error.

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
    Bundle savedInstanceState) {
    adapter=new BuzzFeedCardAdapter(buzzFeedlist,getActivity());
    try {
    View v=inflater.inflate(R.layout.buzz_feed_recycler_view, container, false);
    recycleView=(RecyclerView) v.findViewById(R.id.cardList);
    recycleView.setHasFixedSize(true);
    recycleView.setLayoutManager(layoutManager);
    recycleView.setAdapter(adapter);
    recycleView.setItemAnimator(new DefaultItemAnimator());
    return v;
    } catch (Exception e) {
    e.printStackTrace();
    }
    return null;
    }

    I am getting this error when i navigate back to this fragment from other fragments. Any help is highly appreciated.

    1. Hi, I have a same problem with you.

      if you got solutions for that kinds of problem, could you send me a brief solution via mail?

  14. Nice post, thanks.

    I found this post on item animator http://chikkooos.blogspot.jp/2015/12/creating-custom-animation-in.html
    hope it is useful

  15. I have a question , If I wanna realize comlax ListView . Every item is different. Then how can I use the RecyclerView ?

    1. Not sure, I understand you correctly. If really every item is different, then you shouldn’t use a RecyclerView. The RecyclerView is only useful if there are items to be recycled, that is if there are repeating elements (no matter if those items repeat one after the other or irregularly).

      If you just have a lot of different items you have to override getItemViewType(). And keep these types in mind when dealing with bindViewHolder() and createViewHolder().

  16. Alexander Skvortsov

    Regarding click listeners. A nice way is implement View.OnClickListener (or OnLongClickListener) at your ViewHolder and attach it as listener to corresponding View in RecycleView.Adapter.onBindViewHolder(…). Then it is possible to deliver click to upward Adapter (or Adapter.Listener if it is declared and provided).

  17. Hi Wolfraw, thanks for sharing your knowledge: I have an application which has two buttons on the main activity, the idea is that by giving click on them, I send activity recyclerview which would be the same for the two buttons, the only thing is that by giving click button 1 to display information only on that button and the button 2 to give click to show only the information that button, I appreciate all the information you can give me, thank you.

    1. Wolfram Rittmeyer

      All you need to do is provide your adapter with the correct data. That way you only need one adapter and one recyclerview (if the views of both really are the same).

      1. Wolfraw Hi, thank you very much for your cooperation, I have the following question: when you say I should put the right data, which are the correct data?
        I send you pictures of my first activity java: which is:

        http://snag.gy/CJQho.jpg
        http://snag.gy/no17x.jpg

        And this is the adapter that’m driving:

        http://snag.gy/5DkRP.jpg
        http://snag.gy/556hl.jpg

        What is the data you say that I place or change, I appreciate all your help.

        1. Wolfram Rittmeyer

          I don’t know since it’s your app which data belongs where. But the listclientes is the one you have to change depending on which button is pressed. If it’s a complete different list, simply replace it and call notifyDatasetChanged() within your adapter. If it’s only slightly different it’s probably better to add/remove/change those few items and use more specific notifyXyz() calls.

          If you upload code, BTW, it’s much better to actually paste the source code in text format somewhere (e.g. using Github’s gist) than talking screenshots of the code. Simpler for you, simpler for all those that might want to help.

          1. thanks for your help, as you say I attached the project on github, I hope you can help me because I can not find the way. Thanks and stay tuned to your answer.
            https://github.com/Mario1708/MyProyect

          2. Wolfram Rittmeyer

            I think this has nothing to do with the RecyclerView. It’s basic event handling and Intent usage. Have a look at the official Android trainings by Google. This deals with starting a new Activity based on some action in the first one.

          3. Hi Wolfram: thanks for the info you offer me, I have it tried to do as I indicas but to give in the first button I get all the information from the list and give the second button I get all the information also and the idea as I said is that each of the buttons show me only the information of that button, that is the first solo show me the information of the laboratories and the second only show me information clinics. I appreciate your cooperation and support.

          4. Wolfram Rittmeyer

            At some point you have to filter this list. Be it when querying a database or however you get to the list (I think it’s the server’s JSON response in your case – or it could be calling the right endpoint on your server). Whatever it is for your use case, it is nothing specific to Android. It’s most likely something you can solve with plain Java list handling.

            Only take care to do that before adding the list to the adapter.

  18. Any idea on how to implement a snappy horizontal recyclerView with CardViews that snap the item on focus on the center every time ?

    This solution (http://stackoverflow.com/questions/26370289/snappy-scrolling-in-recyclerview) looks pretty buggy. 🙁 And I haven’t found any other solution.

  19. i am getting java null pointer exception.same code.any help?

Leave a Reply

Your email address will not be published. Required fields are marked *

You can also subscribe without commenting.