Blinking problems encountered while RecyclerView is loading more

Blinking problems encountered while RecyclerView is loading more

Do not use notifyDataSetChanged() when using RecyclerView to load more data. The method who refreshes the whole data set, all views refresh again, there is a flashing problem, analyze from the source code

public abstract static class Adapter<VH extends ViewHolder> {
    ...
     public final void notifyDataSetChanged() {
            mObservable.notifyChanged();
    }
}

 static class AdapterDataObservable extends Observable<AdapterDataObserver> {

     public void notifyChanged() {
            // since onChanged() is implemented by the app, it could do anything, including
            // removing itself from {@link mObservers} - and that could cause problems if
            // an iterator is used on the ArrayList {@link mObservers}.
            // to avoid such problems, just march thru the list in the reverse order.
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
 }

It can be seen from the code that this method refreshes all the data. If you keep tracking, it is actually updating the data. Then recyclerView calls the requestLayout() method
RecyclerView actually provides a better way to target changed data

* @see #notifyItemChanged(int)
* @see #notifyItemInserted(int)
* @see #notifyItemRemoved(int)
* @see #notifyItemRangeChanged(int, int)
* @see #notifyItemRangeInserted(int, int)
* @see #notifyItemRangeRemoved(int, int)

We can see the specific function from the name. Let's look at the common methods

/**
     * Notify any registered observers that the <code>itemCount</code> items starting at
     * position <code>positionStart</code> have changed.
     * Equivalent to calling <code>notifyItemRangeChanged(position, itemCount, null);</code>.
     *
     * <p>This is an item change event, not a structural change event. It indicates that
     * any reflection of the data in the given position range is out of date and should
     * be updated. The items in the given range retain the same identity.</p>
     *
     * @param positionStart Position of the first item that has changed
     * @param itemCount Number of items that have changed
     *
     * @see #notifyItemChanged(int)
     */
    public final void notifyItemRangeChanged(int positionStart, int itemCount) {
        mObservable.notifyItemRangeChanged(positionStart, itemCount);
    }

You don't need to look at the comments and method names to see what they do. They only update the itemCount data changes from positionStart, but the previous view s and data will not change.
This method can solve the problem of flicker
It's said on the Internet
(recyclerCategory.itemAnimator as SimpleItemAnimator).supportsChangeAnimations = false
To solve the flicker problem, this method cancels the animation effect brought by the adapter, but I only need to use notifyItemRangeChanged to solve the problem without similar settings.

Posted on Fri, 01 May 2020 18:56:34 -0700 by zushiba