观察者模式在Android中的应用

时间:2022-09-09 08:41:19

观察者模式在实际使用中是非常方便的,简单来说就是当一个数据源(即被观察者)的数据发生了变动,将自动通知到所有对应的观察者,此时观察者可以根据接收到的通知信息针对数据变动作出相应调整。

举个简单的在Android上的例子,我使用一个Service在后台进行时间倒计时,而我需要在多个Activity上同步显示该倒计时的信息。那么,Service上的倒计时功能即为被观察者Observable),而这多个Activity则为观察者Observer)。

Java自身带有Observable和Observer的接口,我们也可以自己自定义实现Observable和Observer,但是这就要求我们自己在Observable中维护Observer的列表。


首先,我们定义好观察者Observer的接口:

package com.vite.testobserver.observer.ifc;

/**
* 观察者接口
*
* @author trs
*
*/
public interface Observer {
void update(Object data);
}

然后定义被观察者Observable的接口:

package com.vite.testobserver.observer.ifc;

/**
* 被观察者接口
*
* @author trs
*
*/
public interface Observable {
/**
* 添加观察者
*
* @param observer
*/
public void addObserver(Observer observer);

/**
* 删除观察者
*
* @param observer
*/
public void deleteObserver(Observer observer);

/**
* 删除所有观察者
*/
public void deleteObservers();

/**
* 通知所有观察者
*
* @param data
*/
public void notifyObservers(Object data);

/**
* 通知所有观察者
*/
public void notifyObservers();

/**
* 获取观察者数量
*
* @return
*/
public int getCountObservers();
}

然后通过继承Observable的接口,自定义我们自己的被观察者类:

package com.vite.testobserver.observer;

import java.util.ArrayList;
import java.util.List;

import com.vite.testobserver.observer.ifc.Observable;
import com.vite.testobserver.observer.ifc.Observer;

/**
* 自定义被观察者
*
* @author trs
*
*/
public class TimeCountObservable implements Observable {
private static List<Observer> observerList = new ArrayList<Observer>();

public static void GlobalAddObserver(Observer observer) {
if (observerList == null)
throw new NullPointerException();

if (observer == null)
throw new NullPointerException();
synchronized (observerList) {
if (!observerList.contains(observer))
observerList.add(observer);
}
}

public static void GlobalDeleteObserver(Observer observer) {
if (observerList == null)
throw new NullPointerException();

if (observer == null)
throw new NullPointerException();
synchronized (observerList) {
if (observerList.contains(observer))
observerList.remove(observer);
}
}

@Override
public synchronized void addObserver(Observer observer) {
// TODO Auto-generated method stub
if (observerList == null)
throw new NullPointerException();

if (observer == null)
throw new NullPointerException();
synchronized (observerList) {
if (!observerList.contains(observer))
observerList.add(observer);
}
}

@Override
public synchronized void deleteObserver(Observer observer) {
// TODO Auto-generated method stub
if (observerList == null)
throw new NullPointerException();

if (observer == null)
throw new NullPointerException();
synchronized (observerList) {
if (observerList.contains(observer))
observerList.remove(observer);
}
}

@Override
public synchronized void deleteObservers() {
// TODO Auto-generated method stub
if (observerList == null)
throw new NullPointerException();

synchronized (observerList) {
observerList.removeAll(observerList);
}
}

@Override
public void notifyObservers(Object data) {
// TODO Auto-generated method stub
if (observerList == null)
throw new NullPointerException();

synchronized (observerList) {
for (Observer observer : observerList) {
observer.update(data);
}
}
}

@Override
public void notifyObservers() {
// TODO Auto-generated method stub
notifyObservers(null);
}

@Override
public int getCountObservers() {
// TODO Auto-generated method stub
if (observerList == null)
throw new NullPointerException();
synchronized (observerList) {
return observerList.size();
}
}
}
注意代码上面,记录观察者Observer的列表使用了static修饰,同时增加了两各静态方法 GlobalAddObserverGlobalDeleteObserver

这是为了在Service以外的地方动态添加和删除观察者,写得比较简单粗暴,在实际应用过程中我们也可以根据需求进行不同的自定义。


然后,通过对Activity实现观察者Observer接口中的updata方法,并将自身通过GlobalAddObserver加入到观察者列表中。

这样,在后台Service里的倒计时功能中调用notifyObservers方法,通知所有在观察者列表中的观察者,并将数据传递到updata方法中,就完成了一次数据更新。

private class TimeCountDownTimer extends CountDownTimer {

public TimeCountDownTimer(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
// TODO Auto-generated constructor stub
}

@Override
public void onFinish() {
// TODO Auto-generated method stub
timeCountObservable.notifyObservers("00:00");
if (timer != null)
timer.cancel();
timer = null;
}

@Override
public void onTick(long millisUntilFinished) {
// TODO Auto-generated method stub
Date date = new Date(millisUntilFinished);
timeCountObservable.notifyObservers(df.format(date));
}

}


一般而言这样就可以了,但是偶尔会遇到一些情况,就是某个观察者的 updata方法中耗时过长,这样会导致排在该观察者后面的其余观察者的无法及时更新数据。针对这个问题,我们可以用Handler来进行异步处理。

通过实现Observer接口,我们自定义一个可以异步处理的TimeCountObserver:

package com.vite.testobserver.observer;

import android.os.Handler;

import com.vite.testobserver.observer.ifc.Observer;

public abstract class TimeCountObserver implements Observer {
private Handler handler;
private Object object;

public TimeCountObserver(Handler handler) {
this.handler = handler;
}

public abstract void onUpdate(Object data);

@Override
public void update(Object data) {
// TODO Auto-generated method stub
object = data;
if (handler == null)
onUpdate(object);
else
handler.post(new LocalRunnable());
}

private class LocalRunnable implements Runnable {

@Override
public void run() {
// TODO Auto-generated method stub
onUpdate(object);
}

}
}

然后在Activity中就无需实现Observer接口,而是实例化TimeCountObserver,并且通过 onUpdate方法更新数据:

timeCountObserver = new TimeCountObserver(new Handler()) {

@Override
public void onUpdate(Object data) {
// TODO Auto-generated method stub
content.setText(data.toString());
}
};
TimeCountObservable.GlobalAddObserver(timeCountObserver);

效果如下图所示:

观察者模式在Android中的应用


该例子的下载地址如下:

http://download.****.net/detail/vite_s/9391248