模式定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都能得到通知并被自动更新
场景1:短信订阅某资讯,当资讯有更新时通知订阅者
场景2:微信订阅公众号,当公众号有新消息时会通知订阅者
场景中订阅资讯的人即为观察者,观察者不用时刻关注资讯的变化,当资讯有更新时,会立刻通知订阅资讯的人,即观察者;里面存在一对多的关系,资讯可以被多个人订阅,被观察的事物只有一个而观察事物的人可以有多个
类1:Observer:观察者
类2:Observable:被观察者
类3:News:资讯
示例代码:
定义观察者,观察者中只要接受资讯即可,接受的类型定义为泛型
public interface Observer<T> {
void receive(T data);
}
定义被观察者,被观察者提供三个方法,订阅/取消/通知
public class Observable <T> {
private List<Observer<T>> list = new ArrayList<>();
public void register(Observer<T> observer){
if(observer == null)
return;
synchronized (this){
if (!list.contains(observer)){
list.add(observer);
}
}
}
public void unregister(Observer<T> observer){ list.remove(observer); }
public void notifyObserver(T t){
for (Observer<T> observer:list){
observer.receive(t);
}
}
}
定义资讯类News,资讯类中放一个内容属性作为测试,一个构造方法以及get/set方法,
public class News{
private String content;
public News(String content) {
this.content= content;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content= content;
}
}
MainActivity中做测试,当资讯发生变化时Observer是否能接收到通知
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Observer<News> observer1 = new Observer<News>() {
@Override
public void receive(News data) {
Log.i("TAG","观察者1接收到信息:"+data.getContent());
}
};
Observer<News> observer2 = new Observer<News>() {
@Override
public void receive(News data) {
Log.i("TAG","观察者2接收到信息:"+data.getContent());
}
};
Observable<News> observable = new Observable<>();
observable.register(observer1);
observable.register(observer2);
observable.notifyObserver(new News("某路人中奖100w"));
observable.unregister(observer1);//观察者1取消订阅
observable.notifyObserver(new News("某路人中奖100w消息是假的"));
}
}
打印TAG:
I/TAG: 观察者1接收到信息:某路人中奖100w
I/TAG: 观察者2接收到信息:某路人中奖100w
I/TAG: 观察者2接收到信息:某路人中奖100w消息是假的
当观察者1取消订阅时,移除数组不再触发接口。
observable对象持有一个集合,observer对象通过register方法传入observable并加入observable持有的集合中;unregister方法把observer对象移除集合;notifyObserver方法通过遍历集合获得集合内的Observer对象,并把外部传入的参数放入接口从而触发;其实就是接口回调
源码中也有很多用到类似的模式,setOnclickListener使用接口回掉,是一对一的使用,而addListener系列使用的是上面的模式,例如EditText的输入监听
使用addTextChangeListener添加监听 new EditText(this).addTextChangedListener(new TextWatcher() {...})
查看addTextChangeListener方法
public void addTextChangedListener(TextWatcher watcher) {
if (mListeners == null) {
mListeners = new ArrayList<TextWatcher>();
}
mListeners.add(watcher);
}
眼熟,内部同样是加入集合;其它还有很多。
Over!