观察者模式(Observer Pattern)也叫发布订阅模式(Publish\subscribe),定义如下:
Define a one-to-many dependency between objects so that when one object changes state,all its dependents are notified and updated automatically.
定义对象间的一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
定义了观察者更新的操作方法update
定义了观察者的注册,注销接口和被观察者变化的通知接口
抽象观察者类 Observer :
定义了一个更新操作的接口
public interface Observer {
public void update();
}
具体的观察者 ConcreteObserver:
实现了update更新操作
public class ConcreteObserver implements Observer{
@Override
public void update() {
// TODO Auto-generated method stub
System.out.println("we receive message, do update!");
}
}
抽象被观察者类 Subject :
关键是定义注册(register),反注册(unregister),内容改变的通知(notifyObservers)三个方法和观察者的集合变量(Vector observers)。
import java.util.Vector;
public abstract class Subject {
private Vector observers = new Vector();
public void register(Observer observer){
if(!observers.contains(observer)){
observers.add(observer);
}
}
public void unregister(Observer observer){
if(observers.contains(observer)){
observers.remove(observer);
}
}
public void notifyObservers(){
for(Observer o:observers){
o.update();
}
}
}
具体观察者 ConcreteSubject :
public class ConcreteSubject extends Subject{
public void doSomething(){
super.notifyObservers();
}
}
Main方法:
public static void main(String[] args) {
ConcreteSubject concreteSubject = new ConcreteSubject();
Observer observer = new ConcreteObserver();
concreteSubject.register(observer);
concreteSubject.doSomething();
}
程序输出:
we receive message, do update!
对于学校的学生来说,上课铃声响后,学生要上课听讲,老师的上课教书,这是非常熟悉的。其实,这就是一个非常经典的观察者模式(一对多)。
先来看一下我们的类图:
我们定义一个观察者的接口Observer:
public interface Observer {
public void update();
}
然后对应的定义二个观察者学生(Student),老师(Teacher),实现其Observer接口。
public class Student implements Observer {
@Override
public void update() {
// TODO Auto-generated method stub
System.out.println("上课铃声响了,又要听这个老师xxxxxxxx…………");
}
}
public class Teacher implements Observer{
@Override
public void update() {
// TODO Auto-generated method stub
System.out.println("上课铃声响了,又要给这帮孩子…………xxxxxxxx");
}
}
我们再定义被观察者的接口Observable :
public interface Observable {
public void register(Observer oberver);
public void unregister(Observer oberver);
public void notifyDate();
}
再综合单例模式定义一个被观察者铃声类Ringtone ,实现Observable 接口:
import java.util.Vector;
public class Ringtone implements Observable{
private static Ringtone ringtone = new Ringtone();
public static Vector observers = new Vector();
private Ringtone(){
}
public static final Ringtone getRingtoneSinglone(){
return ringtone;
}
@Override
public void register(Observer oberver) {
// TODO Auto-generated method stub
if(!observers.contains(oberver)){
observers.add(oberver);
}
}
@Override
public void unregister(Observer oberver) {
// TODO Auto-generated method stub
if(observers.contains(oberver)){
observers.remove(oberver);
}
}
@Override
public void notifyDate() {
// TODO Auto-generated method stub
for(Observer observer:observers){
observer.update();
}
}
public void ring(){
System.out.println("上课铃声响了!!");
notifyDate();
}
}
Main:
public static void main(String[] args) {
// TODO Auto-generated method stub
Ringtone ringtone = Ringtone.getRingtoneSinglone();
Observer student = new Student();
Observer teacher = new Teacher();
ringtone.register(teacher);
ringtone.register(student);
ringtone.ring();
}
程序输出:
上课铃声响了!!
上课铃声响了,又要给这帮孩子…………xxxxxxxx
上课铃声响了,又要听这个老师xxxxxxxx…………
观察者模式需要考虑开发效率和运行效率。一个被观察者,多个观察者,开发和调试比较复杂,而且java中消息的通知默认是顺序执行,一个观察者卡壳,会影响整体的执行效率。在这种情况下,一般考虑异步的方式。
多级触发的效率更是让人担忧,大家设计时要注意考虑。
在android开发时,我们经常定义一个新的广播(观察者),
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String msg = intent.getStringExtra("msg");
..............
}
}
然后注册,有二种方式:
(1)静态注册
在androidManifest.xml中注册:
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.MY_BROADCAST"/>
<category android:name="android.intent.category.DEFAULT" />
intent-filter>
receiver>
(2)代码动态注册
MyReceiver receiver = new MyReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.MY_BROADCAST");
registerReceiver(receiver, filter);
对应的反注册的方式:
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(receiver);
}
当我们发送对应的Intent时,
Intent intent = new Intent("android.intent.action.MY_BROADCAST");
intent.putExtra("msg", "hello receiver.");
sendBroadcast(intent);
对应的MyReceiver会执行onReceive方法,更新对应的操作。
从上面的使用过程,我们可以清楚的看到:
MyReceiver做为具体的观察者(ConcreteObserver),我们只需要实现其onReceive的更新方法。
BroadcastReceiver 做为抽象观察者(Observer)。
在android源码中:
./frameworks/base/core/java/android/content/BroadcastReceiver.java
看到:
//抽象类 BroadcastReceiver,做为Observer
public abstract class BroadcastReceiver {
............
//定义抽象更新方法onReceive
public abstract void onReceive(Context context, Intent intent);
............
}
在当前Context中,例如Activity,相当于具体的被观察者类,我们调用:
registerReceiver方法注册
unregisterReceiver方法反注册
sendBroadcast方法通知被观察者已经改变,观察者调用onReceive方法更新。
Context类相当于Subject 抽象的被观察者.
在android的源码中:
./frameworks/base/core/java/android/content/Context.java
关键方法:
//抽象被观察者类 Context
public abstract class Context {
.............
//注册方法 registerReceiver
public abstract Intent registerReceiver(@Nullable BroadcastReceiver receiver,IntentFilter filter);
public abstract Intent registerReceiver(BroadcastReceiver receiver,IntentFilter filter, @Nullable String broadcastPermission,@Nullable Handler scheduler);
//反注册方法 unregisterReceiver
public abstract void unregisterReceiver(BroadcastReceiver receiver);
//通知被观察者改变的方法 sendBroadcast
public abstract void sendBroadcast(Intent intent);
public abstract void sendBroadcast(Intent intent, @Nullable String receiverPermission);
public abstract void sendBroadcast(Intent intent,String receiverPermission, int appOp);
...............
}
中间类ContextWrapper :
./frameworks/base/core/java/android/content/ContextWrapper.java
public class ContextWrapper extends Context {
Context mBase;
//构造方法
public ContextWrapper(Context base) {
mBase = base;
}
..........
//注册方法 registerReceiver
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return mBase.registerReceiver(receiver,filter,broadcastPermission,scheduler);
}
/** @hide */
@Override
public Intent registerReceiverAsUser(
BroadcastReceiver receiver, UserHandle user, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return mBase.registerReceiverAsUser(receiver, user,filter, broadcastPermission,scheduler);
}
//反注册方法 unregisterReceiver
@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
mBase.unregisterReceiver(receiver);
}
//通知被观察者改变的方法 sendBroadcast
@Override
public void sendBroadcast(Intent intent) {
mBase.sendBroadcast(intent);
}
@Override
public void sendBroadcast(Intent intent, String receiverPermission) {
mBase.sendBroadcast(intent, receiverPermission);
}
/** @hide */
@Override
public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
mBase.sendBroadcast(intent, receiverPermission,appOp);
}
...............
}
从代码来看,ContextWrapper 类实现了Conext类,在对应的重写方法中,只是调用了mBase变量的对应方法。
那么实现registerReceiver,unregisterReceiver,sendBroadcast三个方法的是类ContextImpl
./frameworks/base/core/java/android/app/ContextImpl.java
/**
* Common implementation of Context API, which provides the base
* context object for Activity and other application components.
*/
class ContextImpl extends Context {
................
//实现注册方法 registerReceiver
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext());
}
@Override
public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
IntentFilter filter, String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, user.getIdentifier(),
filter, broadcastPermission, scheduler, getOuterContext());
}
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
return ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
} catch (RemoteException e) {
return null;
}
}
//反注册方法 unregisterReceiver
@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
if (mPackageInfo != null) {
IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
getOuterContext(), receiver);
try {
ActivityManagerNative.getDefault().unregisterReceiver(rd);
} catch (RemoteException e) {
}
} else {
throw new RuntimeException("Not supported in system context");
}
}
//通知被观察者改变的方法 sendBroadcast
@Override
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess();
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, false, false,
getUserId());
} catch (RemoteException e) {
}
}
@Override
public void sendBroadcast(Intent intent, String receiverPermission) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess();
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE,
false, false, getUserId());
} catch (RemoteException e) {
}
}
@Override
public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess();
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, receiverPermission, appOp, false, false,
getUserId());
} catch (RemoteException e) {
}
}
................
}
可以看到ContextImpl实现registerReceiver,unregisterReceiver,sendBroadcast这三个方法是依靠:
//注册
ActivityManagerNative.getDefault().registerReceiver
//反注册
ActivityManagerNative.getDefault().unregisterReceiver(rd)
//广播
ActivityManagerNative.getDefault().broadcastIntent
我们查看ActivityManagerNative类:
./frameworks/base/core/java/android/app/ActivityManagerNative.java
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
.................
/**
* Retrieve the system's default/global activity manager.
* 返回一个IActivityManager
*/
static public IActivityManager getDefault() {
return gDefault.get();
}
.................
//通过IBinder ,返回IActivityManager
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
//注册
public Intent registerReceiver(IApplicationThread caller, String packageName,
IIntentReceiver receiver,
IntentFilter filter, String perm, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(packageName);
data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);
filter.writeToParcel(data, 0);
data.writeString(perm);
data.writeInt(userId);
mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);
reply.readException();
Intent intent = null;
int haveIntent = reply.readInt();
if (haveIntent != 0) {
intent = Intent.CREATOR.createFromParcel(reply);
}
reply.recycle();
data.recycle();
return intent;
}
//反注册
public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(receiver.asBinder());
mRemote.transact(UNREGISTER_RECEIVER_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
//广播
public int broadcastIntent(IApplicationThread caller,
Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle map,
String requiredPermission, int appOp, boolean serialized,
boolean sticky, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo != null ? resultTo.asBinder() : null);
data.writeInt(resultCode);
data.writeString(resultData);
data.writeBundle(map);
data.writeString(requiredPermission);
data.writeInt(appOp);
data.writeInt(serialized ? 1 : 0);
data.writeInt(sticky ? 1 : 0);
data.writeInt(userId);
mRemote.transact(BROADCAST_INTENT_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
reply.recycle();
data.recycle();
return res;
}
//关键变量,处理跨应用的数据传输
private IBinder mRemote;
}
我们可以看出ActivityManagerNative类中registerReceiver,unregisterReceiver,broadcastIntent三个方法主要是调用mRemote.transact方法。mRemote是IBinder 变量,所以我们能理解,为什么广播是跨应用。
(1).设计模式之禅—第22章 观察者模式