To see how RecyclerView# adapt #notifyDataSetChanged updates data, we need to start with RecyclerView#setAdapter().

RecyclerView# setAdapter () method:

Call the RecyclerView#setAdapterInternal method and then call requestLayout to update the layout.

public void setAdapter(@Nullable Adapter adapter) {
    // bail out if layout is frozen
    setLayoutFrozen(false);
    setAdapterInternal(adapter, false, true);
    processDataSetCompletelyChanged(false);
    requestLayout();
}
Copy the code

RecyclerView#setAdapterInternal method: replace existing Adapter with new Adapter and trigger corresponding Listeners. RecyclerView#mObserver; MObserver is an instance of RecyclerViewDataObserver. ② Call removeAndRecycleViews method. Remove mAttachedScrap. ③ bind the new Adapter to RecyclerView#mObserver. (4) Notify LayoutManager and RecyclerView of the corresponding data changes.

private void setAdapterInternal(@Nullable Adapter adapter, boolean compatibleWithPrevious, Boolean removeAndRecycleViews) {// Unbind old Adapter recycleView #mObserver. MObserver is an instance of RecyclerViewDataObserver. if (mAdapter ! = null) { mAdapter.unregisterAdapterDataObserver(mObserver); mAdapter.onDetachedFromRecyclerView(this); } if (! CompatibleWithPrevious | | removeAndRecycleViews) {/ / empty mAttachedScrap and mChangedScrap; Add ViewHolder in mCachedViews to RecycledViewPool; Empty mCachedViews. removeAndRecycleViews(); } mAdapterHelper.reset(); final Adapter oldAdapter = mAdapter; mAdapter = adapter; if (adapter ! // bind the new Adapter to RecyclerView#mObserver. adapter.registerAdapterDataObserver(mObserver); adapter.onAttachedToRecyclerView(this); } // Notify Layout and RecyclerView of data changes. if (mLayout ! = null) { mLayout.onAdapterChanged(oldAdapter, mAdapter); } mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious); mState.mStructureChanged = true; }Copy the code

Let’s take a look at our focus, how Adapter relates to RecyclerView.

RecyclerView# Adapter# registerAdapterDataObserver (mObserver) :

Firstly, mObserver is a RecyclerViewDataObserver and a member variable of RecyclerView.

public class RecyclerView extends ViewGroup implements ScrollingView,
        NestedScrollingChild2, NestedScrollingChild3 {
    private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
}
Copy the code

Then see RecyclerView# Adapter# registerAdapterDataObserver method:

public abstract static class Adapter<VH extends ViewHolder> {
    private final AdapterDataObservable mObservable = new AdapterDataObservable();
    public void registerAdapterDataObserver(@NonNull AdapterDataObserver observer) {
        mObservable.registerObserver(observer);
    }
}
Copy the code

AdapterDataObservable is a typical observer pattern. It is the observed (the party whose data changes) and inherits the Observable interface:

static class AdapterDataObservable extends Observable<AdapterDataObserver> {
    ...
}
Copy the code

Observable#registerObserver method: Adds the observer object to the list.

public abstract class Observable<T> { protected final ArrayList<T> mObservers = new ArrayList<T>(); public void registerObserver(T observer) { if (observer == null) { throw new IllegalArgumentException("The observer is null."); } synchronized(mObservers) { if (mObservers.contains(observer)) { throw new IllegalStateException("Observer " + observer  + " is already registered."); } mObservers.add(observer); }}... }Copy the code

To summarize, RecyclerView# Adapter# registerAdapterDataObserver method, will the RecyclerViewDataObserver RecyclerView object mObserver as an observer, Added to the mObservable AdapterDataObservable in RecyclerView#Adapter so that the Adapter can act as the observed and notify the RecyclerView of changes.

RecyclerView# Adapter# notifyDataSetChanged method

Now look at how the RecyclerView# adapt #notifyDataSetChanged method updates data.

public final void notifyDataSetChanged() {
    mObservable.notifyChanged();
}
Copy the code

RecyclerView#AdapterDataObservable#notifyChanged

static class AdapterDataObservable extends Observable<AdapterDataObserver> { public void notifyChanged() { // Notify each registered observer that the data has changed. for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onChanged(); }}}Copy the code

Since we’ve registered RecyclerView#RecyclerViewDataObserver as an observer to the AdapterDataObservable, So it calls RecyclerView#RecyclerViewDataObserver#onChanged:

private class RecyclerViewDataObserver extends AdapterDataObserver { @Override public void onChanged() { ... / / to empty mCachedViews processDataSetCompletelyChanged (true); // Call requestLayout to refresh the UI if (! mAdapterHelper.hasPendingUpdates()) { requestLayout(); }}}Copy the code

So they will call to RecyclerView# processDataSetCompletelyChanged method: Add FLAG_UPDATE and FLAG_INVALID flags to mChildHelper and mCachedViews ViewHolder. Add ViewHolder in mCachedViews to RecycledViewPool; Empty mCachedViews.

void processDataSetCompletelyChanged(boolean dispatchItemsChanged) { mDispatchItemsChangedEvent |= dispatchItemsChanged;  mDataSetHasChangedAfterLayout = true; // Add FLAG_UPDATE and FLAG_INVALID flags to mChildHelper and mCachedViews ViewHolder. Add ViewHolder in mCachedViews to RecycledViewPool; Empty mCachedViews markKnownViewsInvalid (); }Copy the code

RecyclerView# markKnownViewsInvalid method: Add FLAG_UPDATE and FLAG_INVALID to the ViewHolder of mChildHelper. Add FLAG_UPDATE and FLAG_INVALID to the ViewHolder of mChildHelper. Add ViewHolder to RecycledViewPool; Empty mCachedViews

Void markKnownViewsInvalid() {// Add FLAG_UPDATE and FLAG_INVALID to ViewHolder in mChildHelper final int childCount = mChildHelper.getUnfilteredChildCount(); for (int i = 0; i < childCount; i++) { final ViewHolder holder = getChildViewHolderInt(mChildHelper.getUnfilteredChildAt(i)); if (holder ! = null && ! holder.shouldIgnore()) { holder.addFlags(ViewHolder.FLAG_UPDATE | ViewHolder.FLAG_INVALID); }}... // Add FLAG_UPDATE and FLAG_INVALID to ViewHolder of mCachedViews and add ViewHolder to RecycledViewPool; Empty mCachedViews mRecycler. MarkKnownViewsInvalid (); }Copy the code

RecyclerView# Recycler# markKnownViewsInvalid method: Add FLAG_UPDATE and FLAG_INVALID to the ViewHolder of mCachedViews and RecycledViewPool; Empty mCachedViews

Void markKnownViewsInvalid() {// Add FLAG_UPDATE and FLAG_INVALID to ViewHolder in mCachedViews final int cachedCount = mCachedViews.size(); for (int i = 0; i < cachedCount; i++) { final ViewHolder holder = mCachedViews.get(i); if (holder ! = null) { holder.addFlags(ViewHolder.FLAG_UPDATE | ViewHolder.FLAG_INVALID); holder.addChangePayload(null); // Add mCachedViews ViewHolder to RecycledViewPool; Empty mCachedViews if (mAdapter = = null | |! mAdapter.hasStableIds()) { // we cannot re-use cached views in this case. Recycle them all recycleAndClearCachedViews();  }}Copy the code

conclusion

RecyclerView#setAdapter(); RecyclerView#setAdapter(); RecyclerView#mObserver; MObserver is an instance of RecyclerViewDataObserver. ② Call removeAndRecycleViews method. Remove mAttachedScrap. ③ bind the new Adapter to RecyclerView#mObserver. (4) Notify LayoutManager and RecyclerView of the corresponding data changes.

2, RecyclerView#Adapter#notifyDataSetChanged method call, notify RecyclerView data changes, mainly do the following work: ① Through the observer mode, the observed Adapter informs the observer RecyclerView of the corresponding change. Add FLAG_UPDATE and FLAG_INVALID flags to mChildHelper and mCachedViews ViewHolder in RecyclerView. Add ViewHolder in mCachedViews to RecycledViewPool; Empty mCachedViews. ③ Call requestLayout to refresh the UI.