定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都能獲得通知並被自動更新。 例如:天氣預報服務,一旦你訂閱該服務,,天天一旦有天氣信息更新,它就會及時向你發送最新的天氣信息。java
定義天氣做爲被觀察者,若是天氣更新,觀察者進行數據更新bash
/**
* 被觀察者接口
*/
public interface Subject {
//註冊觀察者
void registObserver(Observer observer);
//取消註冊
void unRegistObserver(Observer observer);
//通知觀察者
void notifiObservers();
}
複製代碼
/**
* 觀察者接口
*/
public interface Observer<T> {
//數據更新
void update(T t);
}
複製代碼
public class Weather implements Subject {
private Vector<Observer> mObservers = new Vector<>();
public int mTemp;
@Override
public void registObserver(Observer observer) {
this.mObservers.add(observer);
}
@Override
public void unRegistObserver(Observer observer) {
this.mObservers.remove(observer);
}
@Override
public void notifiObservers() {
for (Observer observer : mObservers) {
observer.update(this);
}
}
/**
* 溫度更新後,通知被觀察者
* @param temp
*/
public void updateTemp(int temp){
this.mTemp = temp;
notifiObservers();
}
}
複製代碼
public class Forecast implements Observer<Weather>{
@Override
public void update(Weather weather) {
System.out.println("溫度調整爲:"+weather.mTemp);
}
}
複製代碼
public class ObserverTest {
public static void main(String[] args){
Weather weather = new Weather();
Forecast forecast = new Forecast();
//註冊觀察者
weather.registObserver(forecast);
//被觀察者數據有更新
weather.updateTemp(15);
}
}
複製代碼
當天氣有溫度更新時,天氣預報會收到相應的通知,並進行對應的更新。ide
java中提供了Observerable和Observer相關實現類ui
public class Observable {
private boolean changed = false;
private final ArrayList<Observer> observers;
public Observable() {
observers = new ArrayList<>();
}
//添加觀察者
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!observers.contains(o)) {
observers.add(o);
}
}
//刪除觀察者
public synchronized void deleteObserver(Observer o) {
observers.remove(o);
}
//通知觀察者
public void notifyObservers() {
notifyObservers(null);
}
public void notifyObservers(Object arg) {
Observer[] arrLocal;
synchronized (this) {
//當changed爲true的時候才通知觀察者
if (!hasChanged())
return;
arrLocal = observers.toArray(new Observer[observers.size()]);
clearChanged();
}
for (int i = arrLocal.length - 1; i >= 0; i--)
arrLocal[i].update(this, arg);
}
public synchronized void deleteObservers() {
observers.clear();
}
//將changed設爲true
protected synchronized void setChanged() {
changed = true;
}
//清除狀態
protected synchronized void clearChanged() {
changed = false;
}
//查詢狀態
public synchronized boolean hasChanged() {
return changed;
}
public synchronized int countObservers() {
return observers.size();
}
}
複製代碼
public interface Observer {
void update(Observable o, Object arg);
}
複製代碼
觀察者接口,定義了更新的方法this
(1)被觀察者spa
public class Weather extends Observable {
public int mTemp;
/**
* 溫度更新後,通知被觀察者
* @param temp
*/
public void updateTemp(int temp){
this.mTemp = temp;
setChanged();
notifyObservers(this);
}
}
複製代碼
(2)觀察者code
public class Forecast implements Observer {
@Override
public void update(Observable o, Object arg) {
if (arg instanceof Weather) {
System.out.println("溫度調整爲:"+((Weather) arg).mTemp);
}
}
}
複製代碼
(3)使用cdn
public class ObserverTest {
public static void main(String[] args) {
Weather weather = new Weather();
Forecast forecast = new Forecast();
weather.addObserver(forecast);
weather.updateTemp(20);
}
}
複製代碼
觀察者接受到了通知並進行了更新server
public static abstract class Adapter<VH extends ViewHolder> {
//建立一個被觀察者,用來添加、刪除、通知觀察者
private final AdapterDataObservable mObservable = new AdapterDataObservable();
......
/**
* 註冊觀察者
* @param observer
*/
public void registerAdapterDataObserver(AdapterDataObserver observer) {
mObservable.registerObserver(observer);
}
/**
* 取消註冊觀察者
* @param observer
*/
public void unregisterAdapterDataObserver(AdapterDataObserver observer) {
mObservable.unregisterObserver(observer);
}
/**
* 通知已註冊的觀察者更新數據
*/
public final void notifyDataSetChanged() {
mObservable.notifyChanged();
}
/**
* 通知已註冊的觀察者某個索引的數據發生改變
*/
public final void notifyItemChanged(int position) {
mObservable.notifyItemRangeChanged(position, 1);
}
......
}
複製代碼
static class AdapterDataObservable extends Observable<AdapterDataObserver> {
public boolean hasObservers() {
return !mObservers.isEmpty();
}
/**
* 遍歷觀察者,調用其onChanged方法
*/
public void notifyChanged() {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
/**
* 遍歷觀察者,調用其onItemRangeChanged方法
* @param positionStart
* @param itemCount
* @param payload
*/
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);
}
}
......
}
複製代碼
AdapterDataObservable做爲一個被觀察者,繼承了Observable,在數據發生改變時,遍歷通知觀察者調用其回調方法。對象
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);
}
}
/**
* 取消註冊將觀察者移除
*/
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);
}
}
/**
* 移除全部觀察者
*/
public void unregisterAll() {
synchronized(mObservers) {
mObservers.clear();
}
}
}
複製代碼
public static abstract class AdapterDataObserver {
public void onChanged() {
}
public void onItemRangeChanged(int positionStart, int itemCount) {
}
public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
onItemRangeChanged(positionStart, itemCount);
}
public void onItemRangeInserted(int positionStart, int itemCount) {
}
public void onItemRangeRemoved(int positionStart, int itemCount) {
}
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
}
}
複製代碼
做爲觀察者,定義一些回調方法,在被觀察者發生改變時會被調用
經過Adapter的registerAdapterDataObserver進行註冊
(1)RecyclerView的setAdapter
#RecyclerView
public void setAdapter(Adapter adapter) {
// bail out if layout is frozen
setLayoutFrozen(false);
setAdapterInternal(adapter, false, true);
requestLayout();
}
private void setAdapterInternal(RecyclerView.Adapter adapter, boolean compatibleWithPrevious,
boolean removeAndRecycleViews) {
//先經過以前的adapter將觀察者取消註冊
if (mAdapter != null) {
mAdapter.unregisterAdapterDataObserver(mObserver);
mAdapter.onDetachedFromRecyclerView(this);
}
if (!compatibleWithPrevious || removeAndRecycleViews) {
removeAndRecycleViews();
}
mAdapterHelper.reset();
final RecyclerView.Adapter oldAdapter = mAdapter;
mAdapter = adapter;
//註冊新的觀察者
if (adapter != null) {
adapter.registerAdapterDataObserver(mObserver);
adapter.onAttachedToRecyclerView(this);
}
......
}
複製代碼