Android 觀察者模式,這麼講你還不理解嗎

觀察者模式:顧名思義,就是衆多觀察者(observers)對被觀察者(observable)的狀態、行爲等進行監聽,
             當被觀察者(observable)的狀態、行爲等發生改變後,向觀察者(observers)發出通知,告知觀察者(observers),
            觀察者可以對這些通知進行處理或者不處理。

舉個例子:
比如在上課的時候,老師可以看成一個被觀察者(observable),所有學生可以看成觀察者(observers)
老師(observable)喊上課之後,所有同學(observers)的注意力都集中在老師身上,這時候相當於給被觀察者(observable)添加了許多觀察者(observers);
被觀察者(老師)(observable)的一言一行都會通過光或者聲音反饋給到同學們(observers),當然同學們(observers)對
老師(observable)的言行可能有所反應或者不做任何響應。比如在看到老師(observable)走過來的時候,沒認真聽講的同學(observers)趕緊坐好,集中注意(響應),認真聽講的同學(observers)則可以不做反應。
當然在收到老師(observable)【放學】的通知後,同學們都背起書包回家,即都響應了。

從上面例子可以看出,觀察者(observers)一定要有接收被觀察者(observable)通知的能力;
被觀察者(observable)一定要有增加觀察者(observers)的和通知觀察者(observers)的能力;
那麼我們可以將這些能力抽象出來,讓具體的實現必須實現這些能力,然後添加觀察者(observers)的時候
只關心他有沒有接收通知的能力(即是否是抽象觀察者類observers的實現類)。至此,以及結合高內聚低耦合的思想,我們可以看到,
觀察者模式有4個必要元素:
1.觀察者抽象類
2.觀察者具體實現類
3.被觀察者抽象類
4.被觀察者具體實現類

下面來具體實現以下:

觀察者抽象類:

public abstract class Observerabstract {

    /**
     * 必須有接收通知的能力
     * @param msg
     */
    abstract void update(String msg);
}

觀察者具體實現類:

public class MyObserver extends Observerabstract {
    //傳入名稱,區分不同的觀察者
    private String name;

    public MyObserver(String name) {
        this.name = name;
    }

    @Override
    public void update(String msg) {
        System.out.print(String.format("%s 收到了新消息: %s \n",name,msg));
//        System.out.print(name+ "收到特急書信: "+msg);
//        Log.i("魔教求助信",name+ "收到特急書信: "+msg);
    }
}

被觀察者抽象類:

public abstract class Observableabstract {
    /**
     * 增加觀察者
     * @param observer 觀察者實例對象
     */
    abstract void add(Observerabstract observer);

    /**
     * 移除觀察者
     * @param observer 需要移除的觀察者對象
     */
    abstract void move(Observerabstract observer);

    /**
     * 數據變更是通知觀察者
     */
    abstract void notifyObserver();
}

被觀察者具體實現類:

public class MyObservable extends Observableabstract {
    //保存有多少個觀察者要對此被觀察者進行觀察
    private List<Observerabstract> observerList;

    private String message;

    public MyObservable() {
        observerList = new ArrayList<>();
    }

    
    @Override
    public void add(Observerabstract observer) {
        observerList.add(observer);
    }

    @Override
    public void move(Observerabstract observer) {
        observerList.remove(observer);
    }

    @Override
    public void notifyObserver() {
        for (Observerabstract observer:observerList){
            observer.update(message);
        }
        


    }

    public void setMessage(String message) {
        this.message = message;
        notifyObserver();
    }
}

再來看看咱們recycleview的adapter中的源碼

觀察者抽象類:

  /**
     * Observer base class for watching changes to an {@link Adapter}.
     * See {@link Adapter#registerAdapterDataObserver(AdapterDataObserver)}.
     */
    public abstract static class AdapterDataObserver {
        public void onChanged() {
            // Do nothing
        }

        public void onItemRangeChanged(int positionStart, int itemCount) {
            // do nothing
        }

        public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) {
            // fallback to onItemRangeChanged(positionStart, itemCount) if app
            // does not override this method.
            onItemRangeChanged(positionStart, itemCount);
        }

        public void onItemRangeInserted(int positionStart, int itemCount) {
            // do nothing
        }

        public void onItemRangeRemoved(int positionStart, int itemCount) {
            // do nothing
        }

        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
            // do nothing
        }
    }

觀察者具體實現類:

  private class RecyclerViewDataObserver extends AdapterDataObserver {
        RecyclerViewDataObserver() {
        }

        @Override
        public void onChanged() {
            assertNotInLayoutOrScroll(null);
            mState.mStructureChanged = true;

            processDataSetCompletelyChanged(true);
            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 (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {
                ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);
            } else {
                mAdapterUpdateDuringMeasure = true;
                requestLayout();
            }
        }
    }

被觀察者抽象類:

/**
 * Provides methods for registering or unregistering arbitrary observers in an {@link ArrayList}.
 *
 * This abstract class is intended to be subclassed and specialized to maintain
 * a registry of observers of specific types and dispatch notifications to them.
 *
 * @param T The observer type.
 */
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();
        }
    }
}

被觀察者具體實現類:

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,
                @Nullable 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);
            }
        }
    }

很像吧,還有很多地方都用的觀察者模式呢,比如jetpack裏面! 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章