场景:一个android程序中,存在好几个activity和几个fragment,当一个地方发生改变时,其他地方跟着改变。
看到这个问题,我们通常会想到Handler的sendMessage方式发送消息,在需要的地方接收消息,如果需要在N个activity中改变,就需要接收N次,这种实现就比较繁琐,不适合使用;然后我们还会想到发送广播方式来通知,
自定义一个广播,然后在通知的地方接收广播,这种方式需要开发者先接收广播,在结束的地方取消接听,这种方法同样不适合。
以上两种方式都属于发布----订阅模式,只是在上述场景中使用起来比较繁琐。Android中还封装了一个类,叫做Observable;这个类是被观察者,有了被观察者,那么一定存在一个观察者,所以有一个接口Observer,观察者类只要实现这个接口,就可以观察到被观察者。让我们通过一个简单的示例来了解一下。
首先,创建一个观察者类:
import android.util.Log;
import java.util.Observable;
import java.util.Observer;
/**
* coder
* <p>
* Created by czx on2017/1/11.
*/
public class Coder implements Observer {
private staticfinal String TAG = "Coder.class";
private String name;
public Coder(String name) {
this.name = name;
}
@Override
public void update(Observableobservable, Object data) {
Log.e(TAG, toString() + "观察到新的消息:" + data);
}
@Override
public String toString() {
return "观察者" + name;
}
}
这个类实现了Observer这个接口,重写update方法,当被观察者发布新的消息时,观察者就可以通过update方法接受到这个消息。
接下来,就定义被观察者类:
importjava.util.Observable; /** * DevTechFrontier * Created by czx on 2017/1/11. */ public class DevTechFrontier extends Observable { public void postNewPublication(String news) { setChanged(); notifyObservers(news); } }
这个类代码很少,可以看到它是继承了Observable这个类,我们给他定义一个方法,叫做postNewPublication(String news),这个方法就是用来发布消息的,他里面使用了父类的两个方法:setChanged()、notifyObservers(news);查看源码,发现:
/** * Sets the changed flag for this {@code Observable}. After calling * {@code setChanged()}, {@code hasChanged()} will return {@code true}. */ protected void setChanged() { changed = true; }
这个方法就是用来确定要发消息,发送消息的时候判断changed这个变量,如果为true就发布,具体情况可以查看源码:
/** * Returns the changed flag for this {@code Observable}. * * @return {@code true} when the changed flag for this {@code Observable} is * set, {@code false} otherwise. */ public boolean hasChanged() { return changed; } /** * If {@code hasChanged()} returns {@code true}, calls the {@code update()} * method for every observer in the list of observers using null as the * argument. Afterwards, calls {@code clearChanged()}. * <p> * Equivalent to calling {@code notifyObservers(null)}. */ public void notifyObservers() { notifyObservers(null); } /** * If {@code hasChanged()} returns {@code true}, calls the {@code update()} * method for every Observer in the list of observers using the specified * argument. Afterwards calls {@code clearChanged()}. * * @param data * the argument passed to {@code update()}. */ @SuppressWarnings("unchecked") public void notifyObservers(Object data) { int size = 0; Observer[] arrays = null; synchronized (this) { if (hasChanged()) { clearChanged(); size = observers.size(); arrays = new Observer[size]; observers.toArray(arrays); } } if (arrays != null) { for (Observer observer : arrays) { observer.update(this, data); } } }
有上面的源码可以看出,DevTechFrontier中,调用了父类的notifyObservers()方法发布了消息。
接下来我们在看看具体的测试调用:
DevTechFrontier devTechFrontier = new DevTechFrontier(); Coder coder = new Coder("coder"); Coder coder1 = new Coder("coder1"); Coder coder2 = new Coder("coder2"); Coder coder3 = new Coder("coder3"); devTechFrontier.addObserver(coder); devTechFrontier.addObserver(coder1); devTechFrontier.addObserver(coder2); devTechFrontier.addObserver(coder3); devTechFrontier.postNewPublication("My first new : hello word!");
使用方法也比较简单,首先实例化被观察者和观察者,然后将观察者add到被观察者的观察者列表中,最后就可以发布消息了。
使用效果:
01-1211:20:53.392 12047-12047/com.cn.czx.observertest E/Coder.class: 观察者coder观察到新的消息:Myfirst new : hello word!
01-1211:20:53.392 12047-12047/com.cn.czx.observertest E/Coder.class: 观察者coder1观察到新的消息:Myfirst new : hello word!
01-1211:20:53.392 12047-12047/com.cn.czx.observertest E/Coder.class: 观察者coder2观察到新的消息:Myfirst new : hello word!
01-1211:20:53.392 12047-12047/com.cn.czx.observertest E/Coder.class: 观察者coder3观察到新的消息:Myfirst new : hello word!
在此,一个简单的观察者模式就结束了。
总结一下优缺点(别人总结的>_<):
优点:
1、观察者和被观察者之间抽象耦合,应对业务变化
2、增强系统灵活性、可扩展性
缺点:
在使用观察者模式时,需要考虑开发效率和运行效率问题,java的消息通知默认顺序执行,当程序中包含了一个被观察者和多个观察者的时候,如果一个观察者发生卡顿,就会影响执行效率,这种情况就考虑使用异步的方法。
在实际开发中,我们可以根据具体情况确定使用哪种方式。
在这里介绍一个比较方便的开源库,Greenaobot的EvenBus,使用也是非常简单,可以自行查找使用方法。而且这个库是异步执行。