Published Spring, 2019

Blinking RecyclerViews

RecyclerView’s have a bad habit of “blinking” when they update. Basically, it happens when the view refreshes its images. They briefly disappear and reappear which looks like a “blink”. To prevent this, you set the setHasStableIds value to true on the RecyclerViewAdapter. Then you override the getItemId() method in the adapter and ensure that it always returns the same value for each ID. A simple way to accomplish this is to use the element’s hash code. Here is a blog post on which explains the problem and the fix.

Crashing RecyclerViews

Another quirk of RecyclerViewAdapters is that they sometimes crash when the user selects an item during a refresh. The reason is that the getAdapterPosition() method from the ViewHolder returns a value of -1 if the view is currently refreshing. If you are planning to use this value to reference an element in an array, it will throw an ArrayIndexOutOfBoundsException. In the distant past, we used to employ the getPosition() method. But that method has been deprecated. Unfortunately, the replacement method, getAdapterPosition() doesn’t…you know…work. One solution is to check the result of the getAdapterPosition() method against RecyclerView.NO_POSITION (which is -1) before using the value returned by getAdapterPosition().

But what if you actually need the value right now and can’t just bypass it? In that case, you can use getLayoutPosition() instead. I’ve done a fair amount of testing with getLayoutPosition() and I can confirm that it is far more reliable than getAdapterPosition(). That said, no solution is perfect. And if your layout is influx, you may still get burned.

Another option is reduce the amount of time required for refreshing the RecyclerView. Instead of using notifyDataSetChanged(), which refreshes the entire view, try using a slick, cool class called DiffUtils which allows you to only update the child elements that have changed. Again, this is not perfect. But reducing the time that the app spends recreating the RecyclerView makes it that much less likely that the position will be -1.