转载请注明出处: http://blog.csdn.net/aaa111/article/details/43833757
这其实是观察者模式的一种实现形式
先明确两个身份 1.RefistrantList 通知者 2.Registrant 观察者,这是一个一对多的关系,在有事件更新时,凡是通知者列表内的对象,都会收到通知。
RegistrantList 作为通知者支持对Registrant 的增加(add/addUnique)删除(remove),并且能够发出通知(notifyRegitrants),而Registrant作为观察者,响应通知者发出的通知,调用internalNotifyRegistrant()把add()时携带的Message发出去处理。
总体思想是:一个对象中开辟一个空间用于存放Message,当调用regist方法时将Message存放进去,当调用notify方法时将所有Message取出并发送到MessageQueue中等待处理。
下面我们以android 5.0上 来电流程为例讲一下RegistrantList机制的使用。
注册为观察者
1.PstnIncomingCallNotifier这个类中调用mphoneBase中的registerForNewRingingConnection方法注册为观察者,android中的注册为观察者的方法通常写为registerFor***()形式,即为某事件注册消息通知。
PstnIncomingCallNotifier.java
private void registerForNotifications() { Phone newPhone = mPhoneProxy.getActivePhone(); if (newPhone != mPhoneBase) { unregisterForNotifications(); if (newPhone != null) { Log.i(this, "Registering: %s", newPhone); mPhoneBase = newPhone; // 调用registerForNewRingingConnection()方法往RegistrantList中添加Registrant,**注意参数包括handler和message** mPhoneBase.registerForNewRingingConnection( mHandler, EVENT_NEW_RINGING_CONNECTION, null); mPhoneBase.registerForCallWaiting( mHandler, EVENT_CDMA_CALL_WAITING, null); mPhoneBase.registerForUnknownConnection(mHandler, EVENT_UNKNOWN_CONNECTION, null); } } }
2.然后我们看registerForNewRingingConnection()内部做了哪些操作:
调用addUnique()方法添加为观察者。
phoneBase.java
// Inherited documentation suffices. @Override public void registerForNewRingingConnection( Handler h, int what, Object obj) { checkCorrectThread(h); mNewRingingConnectionRegistrants.addUnique(h, what, obj); }
而这个mNewRingingConnectionRegistrants是什么呢?
protected final RegistrantList mNewRingingConnectionRegistrants = new RegistrantList();
mNewRingingConnectionRegistrants是一个RegistrantList 。
3.添加到通知者列表
用传进来的三个参数新建一个观察者,继续调用RegistrantList内部的add()方法
RefistrantList.java
public synchronized void addUnique(Handler h, int what, Object obj) { // if the handler is already in the registrant list, remove it remove(h); // 新建Registrant add(new Registrant(h, what, obj)); }
3.1新建一个Registrant观察者
public Registrant(Handler h, int what, Object obj) { refH = new WeakReference(h);//Handler 泛型WeakReference this.what = what;//消息类型 userObj = obj;//Object数据对象,用于封装传递的数据 }
3.2添加到通知者要通知的列表中,用列表保存观察者。registrants是一个ArrayList。
ArrayList registrants = new ArrayList(); // of Registrant public synchronized void add(Registrant r) { removeCleared(); registrants.add(r); }
registerForNewRingingConnection()方法完成了往RegistrantList中添加Registrant的操作。
同时我们也看到,RegistrantList管理了一个Registrants列表,Registrants保存了多个Registrant。
发出通知
1.handlePollCalls方法根据RIL发出的Call List对象判断Call的状态,并发出不同的通知,
有新的来电将执行: phone.notifyNewRingingConnection; 形如notify***()也是惯用写法。
GsmCallTracker.java
Connection newRinging = null; //or waiting handlePollCalls(){ ... if (newRinging != null) { mPhone.notifyNewRingingConnection(newRinging); }
2.GSMPhone.java
public void notifyNewRingingConnection(Connection c) { super.notifyNewRingingConnectionP(c); }
调用父类 PhoneBase.java notifyNewRingingConnectionP()发出来电通知
mNewRingingConnectionRegistrants.notifyRegistrants(ar);
前面有说过mNewRingingConnectionRegistrants是一个RegistrantList。
/** * Notify registrants of a new ringing Connection. * Subclasses of Phone probably want to replace this with a * version scoped to their packages */ public void notifyNewRingingConnectionP(Connection cn) { if (!mIsVoiceCapable) return; AsyncResult ar = new AsyncResult(null, cn, null); // 调用RegistrantLis 的notifyRegistrants() 方法 mNewRingingConnectionRegistrants.notifyRegistrants(ar); }
通知者RegistrantList.java
public /*synchronized*/ void notifyRegistrants(AsyncResult ar) { internalNotifyRegistrants(ar.result, ar.exception); }
一般来说观察者不止一个,所以用for循环遍历观察者,调用观察者内部的internalNotifyRegistrant()响应通知
private synchronized void internalNotifyRegistrants (Object result, Throwable exception) { for (int i = 0, s = registrants.size(); i < s ; i++) { Registrant r = (Registrant) registrants.get(i); r.internalNotifyRegistrant(result, exception); } }
响应通知消息
Registrant.java
这里是处理RegistrantList 的通知,主要是将message发出出去。
这里的handler和message是之前调用RegistrantList 的addUnique() 方法时添加进去的(add(new Registrant(h, what, obj));)。
/*package*/ void internalNotifyRegistrant (Object result, Throwable exception) { // 得到handler Handler h = getHandler(); if (h == null) { clear(); } else { Message msg = Message.obtain(); msg.what = what; msg.obj = new AsyncResult(userObj, result, exception); // 发送消息 h.sendMessage(msg); } }
PstnIncomingCallNotifier.java
private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch(msg.what) { case EVENT_NEW_RINGING_CONNECTION: handleNewRingingConnection((AsyncResult) msg.obj); break; case EVENT_CDMA_CALL_WAITING: handleCdmaCallWaiting((AsyncResult) msg.obj); break; case EVENT_UNKNOWN_CONNECTION: handleNewUnknownConnection((AsyncResult) msg.obj); break; default: break; } } };
至于响应通知后续做了什么工作不是这次的重点。
=====补充======
Message msg = Message.obtain(): Handler h = getHandler(); h.sendMessage(msg);
从obtain()的源代码中我们可以知道,它是静态方法,而且只有在spool = null 的情况下才会new出一个Message(),返回一个Message对象,如果在不为空的情况下,Message的对象都是从Message对象池里面拿的实例从而重复使用的,这也为了Android中的Message对象能够更好的回收。
使用Handler中的sendMessage (Message msg)方式来发送消息.
我们可以知道android 中发送消息不管是Message中的几种重载的obtain()方式,还是Handler中的几种重载的sendMessage最终都是通过Handler.sendMessage来发送的,而Handler中的几种sendMessage()重载方法最终都会调用到sendMessageAtTime()方法来完成消息的入队操作。
发送一个消息到消息队列的对尾,它会在处理这个时间的线程中的handleMessage(Message),方法中被接受到并且处理。