1.觀察者模式的定義及使用場景
觀察者模式是一個使用率非常高的模式,它最常用的地方是GUI系統,訂閱-發布系統。因為這個模式的一個重要作用就是解耦,將被觀察者和觀察者解耦,使得它們之間的依賴性更小。
定義:
定義對象間一種一對多的依賴關系,使得每當一個對象改變狀態,則所以依賴于它的對象都會得到通知并被自動更新
使用場景:
關聯行為場景,需要注意的是,關聯行為時可拆分的,而不是“組合”關系;
事件多級觸發場景
跨系統的消息交換場景,如消息隊列、事件總線的處理機制
2. 觀察者模式的優缺點
2.1優點
觀察者和被觀察者之間是抽象解耦,應對業務變化
增強系統靈活性、可擴展性
2.2缺點
在應用觀察者模式時需要考慮一下開發效率和運行效率問題,程序中包括一個被觀察者、多個觀察者、開發和調試等內容會比較復雜,而且在Java中消息的通知默認是順序執行,一個觀察者卡頓,會影響整體的執行效率,在這種情況下,一般考慮采用異步的方式
3. 觀察者模式的實現方式
public interface Observer {
//更新方法
public void update();
}```
public class ConcreteObsever implements Observer {
@Override
public void update() {
System.out.println("接收到信息,并進行處理!");
}
}```
public abstract class Subject {
//定義一個觀察者數組
private List<Observer> observers = new ArrayList<>();
//增加一個觀察者
public void addObserver(Observer o) {
this.observers.add(o);
}
//刪除一個觀察者
public void removeObserver(Observer o) {
this.observers.remove(o);
}
//通知所有觀察者
public void notifyObservers() {
for (Observer o : this.observers) {
o.update();
}
}
}```
public class ConcreteSubject extends Subject {
//具體的業務
public void doSomeThing() {
super.notifyObservers();
}
}```
public class Test {
public static void main(String args[]) {
//創建一個被觀察者
ConcreteSubject subject=new ConcreteSubject();
Observer obs=new ConcreteObsever();
subject.addObserver(obs);
subject.doSomeThing();
}
}```
**4. 觀察者模式在Android中的實際應用**
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()方法重新進行布局,更新用戶的界面。這就是一個觀察者模式!
出處:http://huangjunbin.com/page/2/