观察者模式,是一个比较有用的一个设计模式:通俗的讲就是一个被观察者,多个观察者,被观察者发生了变化,会通知观察者,观察者做出各自的事情。
举个例子: 司马光砸缸的典故我想大家都知道。一个小朋友(被观察者)从水缸的外面掉进了水里,于是开始呼救(发出通知),司马光等(观察者)听到这个呼救的时候就做出各种救命的措施()
我们可以看下android自带的源代码:
package java.util;
public class Observable {
private boolean changed = false;
private Vector<Observer> obs;
public Observable() {
obs = new Vector<>();
}
//添加观察者
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
//删除观察者
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
//通知观察者
public void notifyObservers() {
notifyObservers(null);
}
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
public synchronized void deleteObservers() {
obs.removeAllElements();
}
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
public synchronized int countObservers() {
return obs.size();
}
}
代码不多!并且结构很简单,也就是添加观察者,删除观察者,通知观察者几个方法。
但是我们的需求多种多样,而源码里只提供了update的方法
所以我们一般根本不去继承Observable
下面代码走起!
假设我们有个下载的任务。我们有多个页面需要监测这个下载的任务:
public class DownLoadManager {
private Vector<MyObserver> obs = new Vector<>();
private static final int IS_STARTED = 0;
private static final int IS_LOADING = 1;
public static final int IS_OK = 2;
private int state = 0;
private int currentNum = 0;
public interface MyObserver {
void update(int currentNum);
void updatestate(int state);
}
//添加观察者
public synchronized void addObserver(MyObserver o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
//删除观察者
public synchronized void deleteObserver(MyObserver o) {
obs.removeElement(o);
}
//通知更新
private void notifyObservers() {
Object[] arrLocal;
synchronized (this) {
arrLocal = obs.toArray();
}
for (int i = arrLocal.length - 1; i >= 0; i--)
((MyObserver) arrLocal[i]).update(currentNum);
}
//通知更新状态
private void notifyState() {
Object[] arrLocal;
synchronized (this) {
arrLocal = obs.toArray();
}
for (int i = arrLocal.length - 1; i >= 0; i--)
((MyObserver) arrLocal[i]).updatestate(state);
}
public void startLoad() {
new Thread(
new Runnable() {
@Override
public void run() {
while(currentNum < 100){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
currentNum ++;
notifyObservers();
state = IS_LOADING;
notifyState();
}
state = IS_OK;
notifyState();
}
}
).start();
}
}
再来个页面监测
package com.myobserver;
public class MainActivity extends AppCompatActivity implements DownLoadManager.MyObserver {
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView)findViewById(R.id.textView);
DownLoadManager manager = new DownLoadManager();
manager.addObserver(this);
manager.startLoad();
}
@Override
public void update(final int currentNum) {
runOnUiThread(
new Runnable() {
@Override
public void run() {
tv.setText(currentNum+"");
}
}
);
}
@Override
public void updatestate(int state) {
if(state == DownLoadManager.IS_OK){
runOnUiThread(
new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "下载完成啦", Toast.LENGTH_SHORT).show();
}
}
);
}
}
}
下载完成的提示在屏幕下方,没有截取到哈,大家可以下载代码试试