观察者模式是一个使用率非常高的模式,它最常用的地方是GUI系统,订阅-发布系统。因为这个模式的一个重要作用就是解耦,将被观察者和观察者解耦,使得它们之间的依赖性更小。
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所以依赖于它的对象都会得到通知并被自动更新
在应用观察者模式时需要考虑一下开发效率和运行效率问题,程序中包括一个被观察者、多个观察者、开发和调试等内容会比较复杂,而且在java中消息的通知默认是顺序执行,一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般考虑采用异步的方式
RecycleView是Android中最重要的控件之一,而RecycleView最重要的一个功能就是Adapter。通过我们往RecycleView添加数据后,都会调用Adapter的notifyDataSetChanged()方法,这是为什么? 首先我们看下Adapter的实现,他是RecycleView的一个内部类。
public static abstract class Adapter<VH extends ViewHolder> { private final AdapterDataObservable mObservable = new AdapterDataObservable(); private boolean mHasStableIds = false; public abstract VH onCreateViewHolder(ViewGroup parent, int viewType); public abstract void onBindViewHolder(VH holder, int position); public void onBindViewHolder(VH holder, int position, List<Object> payloads) { onBindViewHolder(holder, position); } public final VH createViewHolder(ViewGroup parent, int viewType) { TraceCompat.beginSection(TRACE_CREATE_VIEW_TAG); final VH holder = onCreateViewHolder(parent, viewType); holder.mItemViewType = viewType; TraceCompat.endSection(); return holder; } public final void bindViewHolder(VH holder, int position) { holder.mPosition = position; if (hasStableIds()) { holder.mItemId = getItemId(position); } holder.setFlags(ViewHolder.FLAG_BOUND, ViewHolder.FLAG_BOUND | ViewHolder.FLAG_UPDATE | ViewHolder.FLAG_INVALID | ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN); TraceCompat.beginSection(TRACE_BIND_VIEW_TAG); onBindViewHolder(holder, position, holder.getUnmodifiedPayloads()); holder.clearPayload(); TraceCompat.endSection(); } public int getItemViewType(int position) { return 0; } public void setHasStableIds(boolean hasStableIds) { if (hasObservers()) { throw new IllegalStateException("Cannot change whether this adapter has " + "stable IDs while the adapter has registered observers."); } mHasStableIds = hasStableIds; } public long getItemId(int position) { return NO_ID; } public abstract int getItemCount(); public final boolean hasStableIds() { return mHasStableIds; } public void onViewRecycled(VH holder) { } public boolean onFailedToRecycleView(VH holder) { return false; } public void onViewAttachedToWindow(VH holder) { } public void onViewDetachedFromWindow(VH holder) { } public final boolean hasObservers() { return mObservable.hasObservers(); } public void registerAdapterDataObserver(AdapterDataObserver observer) { mObservable.registerObserver(observer); } public void unregisterAdapterDataObserver(AdapterDataObserver observer) { mObservable.unregisterObserver(observer); } public void onAttachedToRecyclerView(RecyclerView recyclerView) { } public void onDetachedFromRecyclerView(RecyclerView recyclerView) { } public final void notifyDataSetChanged() { mObservable.notifyChanged(); } public final void notifyItemChanged(int position) { mObservable.notifyItemRangeChanged(position, 1); } public final void notifyItemChanged(int position, Object payload) { mObservable.notifyItemRangeChanged(position, 1, payload); } public final void notifyItemRangeChanged(int positionStart, int itemCount) { mObservable.notifyItemRangeChanged(positionStart, itemCount); } public final void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) { mObservable.notifyItemRangeChanged(positionStart, itemCount, payload); } public final void notifyItemInserted(int position) { mObservable.notifyItemRangeInserted(position, 1); } public final void notifyItemMoved(int fromPosition, int toPosition) { mObservable.notifyItemMoved(fromPosition, toPosition); } public final void notifyItemRangeInserted(int positionStart, int itemCount) { mObservable.notifyItemRangeInserted(positionStart, itemCount); } public final void notifyItemRemoved(int position) { mObservable.notifyItemRangeRemoved(position, 1); } public final void notifyItemRangeRemoved(int positionStart, int itemCount) { mObservable.notifyItemRangeRemoved(positionStart, itemCount); } }我们可以看到notifyDataSetChange()中调用了mObservable.notifyChange()。继续看AdapterDataObservable类
static class AdapterDataObservable extends Observable<AdapterDataObserver> { public boolean hasObservers() { return !mObservers.isEmpty(); } public void notifyChanged() { 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) { for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onItemRangeChanged(positionStart, itemCount, payload); } } public void notifyItemRangeInserted(int positionStart, int itemCount) { for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onItemRangeInserted(positionStart, itemCount); } } public void notifyItemRangeRemoved(int positionStart, int itemCount) { 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); } } }Observable是一个被观察者:
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(); } }}AdapterDataObserver 的派生类RecyclerViewDataObserver: mObserver是RecycleView的一个变量
private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver(); private class RecyclerViewDataObserver extends AdapterDataObserver { @Override public void onChanged() { assertNotInLayoutOrScroll(null); if (mAdapter.hasStableIds()) { // TODO Determine what actually changed. // This is more important to implement now since this callback will disable all // animations because we cannot rely on positions. mState.mStructureChanged = true; setDataSetChangedAfterLayout(); } else { mState.mStructureChanged = true; setDataSetChangedAfterLayout(); } if (!mAdapterHelper.haspendingUpdates()) { requestLayout(); } } @Override public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { assertNotInLayoutOrScroll(null); if (mAdapterHelper.onItemRangeChanged(positionStart, itemCount, payload)) { triggerUpdateProcessor(); } } @Override public void onItemRangeInserted(int positionStart, int itemCount) { assertNotInLayoutOrScroll(null); if (mAdapterHelper.onItemRangeInserted(positionStart, itemCount)) { triggerUpdateProcessor(); } } @Override public void onItemRangeRemoved(int positionStart, int itemCount) { assertNotInLayoutOrScroll(null); if (mAdapterHelper.onItemRangeRemoved(positionStart, itemCount)) { triggerUpdateProcessor(); } } @Override public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { assertNotInLayoutOrScroll(null); if (mAdapterHelper.onItemRangeMoved(fromPosition, toPosition, itemCount)) { triggerUpdateProcessor(); } } void triggerUpdateProcessor() { if (mPostUpdatesOnAnimation && mHasFixedSize && mIsAttached) { ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable); } else { mAdapterUpdateDuringMeasure = true; requestLayout(); } } }RecycleView的setAdapter方法,可以看到里面调用了unregisterAdapterDataObserver及registerAdapterDataObserver方法进行取消注册及注册。
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(); }到这里我们知道,setAdapter()方法会进行观察者的注册,当RecycleView的数据发送变化的时,调用了Adapter的notifyDataSetChange(),这个函数又会调用 AdapterDataObservable的notifyChanged();该函数会遍历所有的观察者的onChange函数,在 RecyclerViewDataObserver的onChange()函数中会获取Adapter中数据集的新数量,然后调用RecycleView的requestLayout()方法重新进行布局,更新用户的界面。这就是一个观察者模式!
新闻热点
疑难解答