观察者模式在Android中的应用

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

举个简单的在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);

效果如下图所示:



该例子的下载地址如下:

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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值