观察者模式,使用过RxJava的应该都体验过,这就是一个标准的观察者模式,通过监听数据的变化,来刷新界面,这也复合MVVM架构思想。
1 简单的观察者模式
观察者模式需要的对象:
1 抽象的观察者:提供更新方法,接收消息;
2 具体的观察者:接收消息的具体实现,做后续操作;
3 抽象的被观察者:接收订阅者,给订阅者发消息,移除订阅者;
4 具体的被观察者:具体实现。
还是拿微信公众号发消息来说,这可能是老生常谈了。
/**
* 抽象观察者
*/
public interface IObserver {
/**
* 数据更新
* @param message 接收到的数据
*/
void update(String message);
}
/**
* 具体的观察者
*/
public class XiaoMing implements IObserver{
@Override
public void update(String message) {
System.out.println("XiaoMing接收到了:"+message);
}
}
/**
* 抽象的被观察者
*/
public interface IObservable {
void subscribe(IObserver observer);
void remove(IObserver observer);
void push(String message);
}
/**
* 具体的被观察者
*/
public class BasketballObservable implements IObservable{
private List<IObserver> userList;
public BasketballObservable(){
userList = new ArrayList<>();
}
//订阅者
@Override
public void subscribe(IObserver observer) {
if(!userList.contains(observer)){
userList.add(observer);
}
}
//移除订阅者
@Override
public void remove(IObserver observer) {
if(userList.contains(observer)){
userList.remove(observer);
}
}
@Override
public void push(String message) {
for (IObserver observer :
userList) {
//给订阅者发消息
observer.update(message);
}
}
}
小明订阅了篮球公众号,公众号给小明发消息。
//订阅者小明
IObserver observer = new XiaoMing();
BasketballObservable observable = new BasketballObservable();
//小明订阅了篮球公众号
observable.subscribe(observer);
//发布公众号消息
observable.push("阿尔德里奇重回篮网!!");
运行结果:
XiaoMing接收到了:阿尔德里奇重回篮网!!
2 Java中的观察者模式
Java的Observer
public interface Observer {
/**
* 接收数据
*
* @param o 被观察者
* @param arg 接收的数据
* method.
*/
void update(Observable o, Object arg);
}
具体的观察者James,实现了Java中的IObserver接口
public class James implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("James接收到了:"+arg.toString());
}
}
Java的Observable
public class Observable {
//默认是false
private boolean changed = false;
//装载观察者的集合
private Vector<Observer> obs;
/** Construct an Observable with zero Observers. */
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) {
/*
* a temporary array buffer, used as a snapshot of the state of
* current Observers.
*/
Object[] arrLocal;
synchronized (this) {
//如果
if (!hasChanged())
return;
arrLocal = obs.toArray();
clearChanged();
}
//调用Observer的update方法
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;
}
/**
* Tests if this object has changed.
*
* @return <code>true</code> if and only if the <code>setChanged</code>
* method has been called more recently than the
* <code>clearChanged</code> method on this object;
* <code>false</code> otherwise.
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#setChanged()
*/
public synchronized boolean hasChanged() {
return changed;
}
/**
* Returns the number of observers of this <tt>Observable</tt> object.
*
* @return the number of observers of this object.
*/
public synchronized int countObservers() {
return obs.size();
}
}
James james = new James();
WeatherObservable observable = new WeatherObservable();
//订阅
observable.addObserver(james);
//通知
observable.notifyObservers("明天气温降至-20摄氏度");
运行结果:空
为什么观察者没有接收到消息,看下源码。
public void notifyObservers(Object arg) {
/*
* a temporary array buffer, used as a snapshot of the state of
* current Observers.
*/
Object[] arrLocal;
synchronized (this) {
//如果changed状态为false,那么直接return
if (!hasChanged())
return;
arrLocal = obs.toArray();
clearChanged();
}
//调用Observer的update方法
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
这里需要将changed字段的值置为true,代表数据状态发生改变,才可以通知到观察者。
James james = new James();
WeatherObservable observable = new WeatherObservable();
//订阅
observable.addObserver(james);
//将changed设置为true
observable.setChanged();
//通知
observable.notifyObservers("明天气温降至-20摄氏度");
运行结果:
James接收到了:明天气温降至-20摄氏度
3 ListView中的观察者模式
场景:动态添加数据,刷新ListView列表
3.1 优化观察者模式
在简单的观察者模式中,数据更新使用的数据是String字符串,不具备扩展性,需要优化一下,使用泛型。
/**
* 抽象的观察者
* @param <T> 观察的数据类型
*/
public interface IObserver<T> {
void update(T t);
}
/**
* 具体的观察者
*/
public abstract class Observer implements IObserver<Data>{
@Override
public void update(Data data) {
}
}
/**
* 被观察者
* @param <T> 观察数据泛型
* @param <O> 观察者泛型
*/
public class Observable<T,O extends IObserver<T>> {
private List<O> observers;
public Observable(){
observers = new ArrayList<>();
}
public void subscribe(O o){
if(!observers.contains(o)){
observers.add(o);
}
}
public void unSubscribe(O o){
if(observers.contains(o)){
observers.remove(o);
}
}
public void push(T t){
for (O observer :
observers) {
observer.update(t);
}
}
}
通过改进的观察者模式,更具有灵活性,可选择不同的数据类型传递。
public class DataInsertManager {
//被观察者
Observable<Data,IObserver<Data>> observable;
private DataInsertManager(){
observable = new Observable<>();
}
private static DataInsertManager mInstance;
public static DataInsertManager getInstance(){
if(mInstance == null){
synchronized (DataInsertManager.class){
if(mInstance == null){
mInstance = new DataInsertManager();
}
}
}
return mInstance;
}
public void Insert(Data data){
//插入数据后,通知观察者更新数据
observable.push(data);
}
public void register(IObserver observer){
observable.subscribe(observer);
}
public void unRegister(IObserver observer){
observable.unSubscribe(observer);
}
}
这里将Activity界面作为观察者,动态观察数据的变化,当数据变化时,动态刷新ListView
public class DataActivity extends AppCompatActivity implements IObserver<Data> {
private ListView lv_data;
private DataAdapter mAdapter;
private List<Data> dataList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_data);
lv_data = findViewById(R.id.lv_data);
dataList = new ArrayList<>();
setAdapter(this);
//注册
DataInsertManager.getInstance().register(this);
}
private void setAdapter(Context context) {
if(mAdapter == null){
mAdapter = new DataAdapter(context,dataList);
lv_data.setAdapter(mAdapter);
}else {
//数据更新
mAdapter.notifyDataSetChanged();
}
}
public void addData(View view){
EditText et_name,et_age;
View view1 = View.inflate(this, R.layout.layout_insert, null);
et_name = view1.findViewById(R.id.et_name);
et_age = view1.findViewById(R.id.et_age);
//插入数据
Dialog dialog = new AlertDialog.Builder(this)
.setView(view1)
.setNegativeButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//插入数据
DataInsertManager.getInstance().
Insert(new Data(et_name.getText().toString(),
et_age.getText().toString()));
}
})
.setPositiveButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.create();
dialog.show();
}
//订阅接收到消息
@Override
public void update(Data data) {
//数据更新
dataList.add(data);
//适配器刷新
mAdapter.notifyDataSetChanged();
}
}