想研究清楚RecyclerView#Adapter#notifyDataSetChanged 是如何更新数据的,我们需要从RecyclerView#setAdapter() 方法看起。
RecyclerView#setAdapter()方法:
主要是调用了RecyclerView#setAdapterInternal 方法,然后调用requestLayout 进行布局更新。
public void setAdapter(@Nullable Adapter adapter) {
// bail out if layout is frozen
setLayoutFrozen(false);
setAdapterInternal(adapter, false, true);
processDataSetCompletelyChanged(false);
requestLayout();
}
RecyclerView#setAdapterInternal 方法:将原有的Adapter 替换为新的Adapter ,同时触发对应的Listeners。 ①给原来的Adapter 解除与RecyclerView#mObserver 的绑定。mObserver 是RecyclerViewDataObserver 的实例。 ②调用removeAndRecycleViews 方法。清除mAttachedScrap 。 ③将新的Adapter与RecyclerView#mObserver 进行绑定。 ④通知LayoutManager 和RecyclerView 相应的数据变更。
private void setAdapterInternal(@Nullable Adapter adapter, boolean compatibleWithPrevious,
boolean removeAndRecycleViews) {
// 给原来的Adapter解除与RecyclerView#mObserver的绑定。mObserver是RecyclerViewDataObserver的实例。
if (mAdapter != null) {
mAdapter.unregisterAdapterDataObserver(mObserver);
mAdapter.onDetachedFromRecyclerView(this);
}
if (!compatibleWithPrevious || removeAndRecycleViews) {
// 清空mAttachedScrap和mChangedScrap;将mCachedViews中的ViewHolder添加到RecycledViewPool中;清空mCachedViews。
removeAndRecycleViews();
}
mAdapterHelper.reset();
final Adapter oldAdapter = mAdapter;
mAdapter = adapter;
if (adapter != null) {
// 将新的Adapter与RecyclerView#mObserver进行绑定。
adapter.registerAdapterDataObserver(mObserver);
adapter.onAttachedToRecyclerView(this);
}
// 通知Layout和RecyclerView数据变更。
if (mLayout != null) {
mLayout.onAdapterChanged(oldAdapter, mAdapter);
}
mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious);
mState.mStructureChanged = true;
}
接下来看一下我们的重点,Adapter 是如何与RecyclerView 关联起来的。
RecyclerView#Adapter#registerAdapterDataObserver(mObserver):
首先,mObserver 是RecyclerViewDataObserver ,是RecyclerView 的成员变量。
public class RecyclerView extends ViewGroup implements ScrollingView,
NestedScrollingChild2, NestedScrollingChild3 {
private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
}
接着看RecyclerView#Adapter#registerAdapterDataObserver 方法:
public abstract static class Adapter<VH extends ViewHolder> {
private final AdapterDataObservable mObservable = new AdapterDataObservable();
public void registerAdapterDataObserver(@NonNull AdapterDataObserver observer) {
mObservable.registerObserver(observer);
}
}
AdapterDataObservable 是典型的观察者模式 ,它是被观察者(数据发生变动的一方) ,继承了Observable 接口:
static class AdapterDataObservable extends Observable<AdapterDataObserver> {
...
}
Observable#registerObserver 方法:将观察者对象添加进列表 。
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);
}
}
...
}
总结一下,RecyclerView#Adapter#registerAdapterDataObserver 方法,会将RecyclerView 中的RecyclerViewDataObserver 对象mObserver 当做观察者,添加到RecyclerView#Adapter 中的AdapterDataObservable 对象mObservable 中,这样Adapter 就可以作为被观察者,通知RecyclerView (观察者)数据变动了。
RecyclerView#Adapter#notifyDataSetChanged方法
接着来看下RecyclerView#Adapter#notifyDataSetChanged 方法是如何更新数据的。
public final void notifyDataSetChanged() {
mObservable.notifyChanged();
}
这样就调用到了RecyclerView#AdapterDataObservable#notifyChanged 方法:
static class AdapterDataObservable extends Observable<AdapterDataObserver> {
public void notifyChanged() {
// 通知每个注册的观察者,数据有变动。
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
由于我们已经将RecyclerView#RecyclerViewDataObserver 当做观察者注册给AdapterDataObservable 了,所以会调用到RecyclerView#RecyclerViewDataObserver#onChanged 方法:
private class RecyclerViewDataObserver extends AdapterDataObserver {
@Override
public void onChanged() {
...
// 清空mCachedViews
processDataSetCompletelyChanged(true);
// 调用requestLayout,刷新UI
if (!mAdapterHelper.hasPendingUpdates()) {
requestLayout();
}
}
}
所以会调用到RecyclerView#processDataSetCompletelyChanged 方法:给 mChildHelper 中和 mCachedViews 的ViewHolder 添加 FLAG_UPDATE 和 FLAG_INVALID 标记。并将mCachedViews 中的ViewHolder 添加到到RecycledViewPool 中;清空mCachedViews 。
void processDataSetCompletelyChanged(boolean dispatchItemsChanged) {
mDispatchItemsChangedEvent |= dispatchItemsChanged;
mDataSetHasChangedAfterLayout = true;
// 给 mChildHelper 中和 mCachedViews 的ViewHolder添加 FLAG_UPDATE 和 FLAG_INVALID 标记。并将mCachedViews中的ViewHolder添加到到RecycledViewPool中;清空mCachedViews
markKnownViewsInvalid();
}
RecyclerView#markKnownViewsInvalid 方法: ①给mChildHelper 中的ViewHolder 添加 FLAG_UPDATE 和 FLAG_INVALID 标记 ②给mCachedViews 中的ViewHolder 添加 FLAG_UPDATE 和 FLAG_INVALID 标记,并将ViewHolder 添加到到RecycledViewPool 中;清空mCachedViews
void markKnownViewsInvalid() {
// 给mChildHelper中的ViewHolder添加 FLAG_UPDATE 和 FLAG_INVALID 标记
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);
}
}
...
// 给mCachedViews中的ViewHolder添加 FLAG_UPDATE 和 FLAG_INVALID 标记,并将ViewHolder添加到到RecycledViewPool中;清空mCachedViews
mRecycler.markKnownViewsInvalid();
}
RecyclerView#Recycler#markKnownViewsInvalid 方法: ①给 mCachedViews 中的ViewHolder 添加 FLAG_UPDATE 和 FLAG_INVALID 标记 ②将mCachedViews 中的ViewHolder 添加到RecycledViewPool 中;清空mCachedViews
void markKnownViewsInvalid() {
// 给 mCachedViews 中的ViewHolder添加 FLAG_UPDATE 和 FLAG_INVALID 标记
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);
}
}
// 将mCachedViews中的ViewHolder添加到RecycledViewPool中;清空mCachedViews
if (mAdapter == null || !mAdapter.hasStableIds()) {
// we cannot re-use cached views in this case. Recycle them all
recycleAndClearCachedViews();
}
}
总结
1、调用RecyclerView#setAdapter()方法后:将原有的Adapter 替换为新的Adapter ,同时触发对应的Listeners。 ①给原来的Adapter 解除与RecyclerView#mObserver 的绑定。mObserver 是RecyclerViewDataObserver 的实例。 ②调用removeAndRecycleViews 方法。清除mAttachedScrap 。 ③将新的Adapter与RecyclerView#mObserver 进行绑定。 ④通知LayoutManager 和RecyclerView 相应的数据变更。
2、RecyclerView#Adapter#notifyDataSetChanged 方法调用后,通知RecyclerView 数据变化,主要做了以下工作: ①通过观察者模式 ,由被观察者Adapter 通知观察者RecyclerView 进行对应的变更。 ②RecyclerView 中,给 mChildHelper 中和 mCachedViews 的ViewHolder 添加 FLAG_UPDATE 和 FLAG_INVALID 标记。并将mCachedViews 中的ViewHolder 添加到到RecycledViewPool 中;清空mCachedViews 。 ③调用requestLayout 刷新UI。
|