Android 中 RegistrantList消息处理机制 以android 5.0 MT为例

这其实是观察者模式的一种实现形式

先明确两个身份 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),方法中被接受到并且处理。

Comments
Write a Comment