关于RecyclerView的Adapter的notifyItemInserted()的一些分析
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/51698261
本篇文章主要是针对RecyclerView的Adapter的notifyItemInserted()等方法进行分析,不涉及过多的源码分析,毕竟RecyclerView的代码有11037行,个人水平有限。
我们知道RecyclerView的Adapter与ListView的Adapter相比较,主要有一下的几点不同
1)在ListView的Adapter里面,holder这个类是需要我们自己实现的,同时需要我们判断convertView是否为空,典型的做法如下:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
BaseViewHolder viewHolder = null;
switch (getItemViewType(position)) {
case ITEM_MORE://如果是最后一个位置 就显示MoreHolder
if (convertView == null) {
viewHolder = getMoreViewHolder();
} else {
viewHolder = (BaseViewHolder) convertView.getTag();
break;
default://因为可能还有其他不同的条目,所有用defalut,通过getHolder()由子类去返回不同的条目
if (convertView == null) {
viewHolder = getHolder();//不能通过构造方法传viewHolder,否则只能显示一个,其他都为空
} else {
viewHolder = (BaseViewHolder) convertView.getTag();
viewHolder.setDataToView(getItem(position));
break;
mDisplayedHolders.add(viewHolder);
return viewHolder.getConvertView();
}
而在RecyclerView的adapter里面,我们不需要判断convertView是否为空,我们只需要写ViewHolder就好了,它会自动帮我们复用 2)RecyclerView的Adpater里面相比较ListView的Adapter,主要多了这几个方法
void notifyItemChanged(int position)
final void notifyItemChanged(int position, Object payload)
final void notifyItemRangeChanged(int positionStart, int itemCount)
final void notifyItemRangeChanged(int positionStart, int itemCount, Object payload)
那notifyItemInserted(int position)是怎样实现的呢?我们跟踪代码可以发现,会调用以下的方法:
public final void notifyItemInserted(int position) {
mObservable.notifyItemRangeInserted(position, 1);
}
那这个mObservable到底是什么东西呢?阅读Adapter里面的代码可知,它是里面的一个成员变量,继承于Observable
public static abstract class Adapter<VH extends ViewHolder> {
private final AdapterDataObservable mObservable = new AdapterDataObservable();
- - - -
}
我们先来看Observable里面的代码,我们知道这是一个典型的观察者模式的实现。
如果对观察者模式还不了解的,建议先阅读这篇文章: 观察者设计模式 Vs 事件委托(java)
public abstract class Observable<T> {
* The list of observers. An observer can be in the list at most
* once and will never be null.
protected final ArrayList<T> mObservers = new ArrayList<T>();
* Adds an observer to the list. The observer cannot be null and it must not already
* be registered.
* @param observer the observer to register
* @throws IllegalArgumentException the observer is null
* @throws IllegalStateException the observer is already registered
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);
* Removes a previously registered observer. The observer must not be null and it
* must already have been registered.
* @param observer the observer to unregister
* @throws IllegalArgumentException the observer is null
* @throws IllegalStateException the observer is not yet registered
public void unregisterObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
synchronized(mObservers) {
int index = mObservers.indexOf(observer);
if (index == -1) {
throw new IllegalStateException("Observer " + observer + " was not registered.");
mObservers.remove(index);
* Remove all registered observers.
public void unregisterAll() {
synchronized(mObservers) {
mObservers.clear();
}
接着我们来看这个mObservable是在什么时候初始化的呢,我们回到setAdapter()这个方法
public void setAdapter(Adapter adapter) {
// bail out if layout is frozen
setLayoutFrozen(false);
setAdapterInternal(adapter, false, true);
requestLayout();
private void setAdapterInternal(Adapter adapter, boolean compatibleWithPrevious,
boolean removeAndRecycleViews) {
if (mAdapter != null) {
mAdapter.unregisterAdapterDataObserver(mObserver);
mAdapter.onDetachedFromRecyclerView(this);
if (!compatibleWithPrevious || removeAndRecycleViews) {
// end all running animations
if (mItemAnimator != null) {
mItemAnimator.endAnimations();
// Since animations are ended, mLayout.children should be equal to
// recyclerView.children. This may not be true if item animator's end does not work as
// expected. (e.g. not release children instantly). It is safer to use mLayout's child
// count.
if (mLayout != null) {
mLayout.removeAndRecycleAllViews(mRecycler);
mLayout.removeAndRecycleScrapInt(mRecycler);
// we should clear it here before adapters are swapped to ensure correct callbacks.
mRecycler.clear();
mAdapterHelper.reset();
final Adapter oldAdapter = mAdapter;
mAdapter = adapter;
if (adapter != null) {
adapter.registerAdapterDataObserver(mObserver);
adapter.onAttachedToRecyclerView(this);
if (mLayout != null) {
mLayout.onAdapterChanged(oldAdapter, mAdapter);
mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious);
mState.mStructureChanged = true;
markKnownViewsInvalid();
}
在setAdapterInternal里面主要逻辑就是判断apdter是否为空,不为空的话调用mAdapter.unregisterAdapterDataObserver(mObserver);反注销掉mObserver 接着再调用adapter.registerAdapterDataObserver(mObserver); adapter.onAttachedToRecyclerView(this); 重新注册mObserver和依附到recycleView中。
确定了AdapterDataObservable这个类是什么时候初始化以后,接着我们再回到AdapterDataObservable 这个类
static class AdapterDataObservable extends Observable<AdapterDataObserver> {
public boolean hasObservers() {
return !mObservers.isEmpty();
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();
public void notifyItemRangeChanged(int positionStart, int itemCount) {
notifyItemRangeChanged(positionStart, itemCount, null);
public void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) {
// since onItemRangeChanged() 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).onItemRangeChanged(positionStart, itemCount, payload);
public void notifyItemRangeInserted(int positionStart, int itemCount) {
// since onItemRangeInserted() 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).onItemRangeInserted(positionStart, itemCount);
public void notifyItemRangeRemoved(int positionStart, int itemCount) {
// since onItemRangeRemoved() 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).onItemRangeRemoved(positionStart, itemCount);
public void notifyItemMoved(int fromPosition, int toPosition) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onItemRangeMoved(fromPosition, toPosition, 1);
}
阅读了这个类的源码以后,我们惊喜地发现,这个类里面的notify方法是不是跟adapter里面的notify方法很相似,让我们来看看这个类里面的notify方法具体做了什么? 以insert为例。
public final void notifyItemInserted(int position) {
mObservable.notifyItemRangeInserted(position, 1);
}
调用了mObservable的notifyItemRangeInserted方法,也就是我们上面分析的AdapterDataObservable的notifyItemRangeInserted方法。看看这个方法具体做了什么。
public void notifyItemRangeInserted(int positionStart, int itemCount) {
// since onItemRangeInserted() 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).onItemRangeInserted(positionStart, itemCount);
}
把它内部的mObservers遍历一遍,调用onItemRangeInserted方法,这下大家明白了吧。其实就是obeservable去通知oberser,调用onItemRangeInserted。
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
assertNotInLayoutOrScroll(null);
if (mAdapterHelper.onItemRangeInserted(positionStart, itemCount)) {
triggerUpdateProcessor();
void triggerUpdateProcessor() {
if (mPostUpdatesOnAnimation && mHasFixedSize && mIsAttached) {