Android 基础篇 -- Registrant

 在Tele工作时,遇到过很多的Registrant,此前没有系统的研究过,趁此空挡,查看了下源码,算是做个笔记。

 个人对于Registrant的理解是:一个对象A向另一个对象B注册消息,当B满足或者受到这个消息的时候,就通知A,A在此时去处理某些事。例如在创建Phone对象是,GsmCdmaPhone 会向Ril去注册一条voice_radio_tech_change的消息,当ril收到modem上报的voice_radio_tech_change时候,就会广播出这条消息给GsmCdmaPhone,然后GsmCdmaPhone做相应的处理。其实这也就是一种消息的传递。

 部分代码实现如下:

http://androidxref.com/8.0.0_r4/xref/frameworks/opt/telephony/src/java/com/android/internal/telephony/GsmCdmaPhone.java#265
/**
  *GsmCdmaPhone#initOnce
  * 初始化phone对象是向Ril注册消息
  */
mCi.registerForVoiceRadioTechChanged(this, EVENT_VOICE_RADIO_TECH_CHANGED, null);

在Ril.java里查看该方法的实现

http://androidxref.com/8.0.0_r4/xref/frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java

/**
  * 在Ril.java中未发现该方法的实现,
  * 继续在其父类中寻找
  */
public final class RIL extends BaseCommands implements CommandsInterface


http://androidxref.com/8.0.0_r4/xref/frameworks/opt/telephony/src/java/com/android/internal/telephony/BaseCommands.java

/**
  * 该方法由三个参数,分别为Handler,what,obj;
  * 
  */
@Override
public void registerForVoiceRadioTechChanged(Handler h, int what, Object obj) {
    Registrant r = new Registrant (h, what, obj);
    mVoiceRadioTechChangedRegistrants.add(r);
}   

继续查看该注册方法的具体实现

http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/os/Registrant.java#28
/**
  * 首先为创建了Registrant的对象,查看其构造函数
  * 传入的三个参数
  */
    public
    Registrant(Handler h, int what, Object obj)
    {
        refH = new WeakReference(h);
        this.what = what;
        userObj = obj;
    }

/**
  * 其次查看mVoiceRadioTechChangedRegistrants 
  * 
  */
protected RegistrantList mVoiceRadioTechChangedRegistrants = new RegistrantList();


public synchronized void add(Registrant r) {
    removeCleared();
    registrants.add(r);
}



至此,GsmCdmaPhone 已经执行完了mCi.registerForVoiceRadioTechChanged(this, EVENT_VOICE_RADIO_TECH_CHANGED, null); 即GsmCdmaPhone向 Ril注册了一条voice_radio_tech_changed的消息。

既然已经注册了消息,那么当满足该消息时,RIL应该告知该注册者。

代码如下:

http://androidxref.com/8.0.0_r4/xref/frameworks/opt/telephony/src/java/com/android/internal/telephony/RadioIndication.java#619

/**
  * 当voice_radio_tech_change的时候,mVoiceRadioTechChangedRegistrants会去通知所有注册这条消
  * 息的对象
  */
    public void voiceRadioTechChanged(int indicationType, int rat) {
        mRil.processIndication(indicationType);

        int response[] = new int[1];
        response[0] = rat;

        if (RIL.RILJ_LOGD) mRil.unsljLogRet(RIL_UNSOL_VOICE_RADIO_TECH_CHANGED, response);

        mRil.mVoiceRadioTechChangedRegistrants.notifyRegistrants(
                new AsyncResult (null, response, null));
    } 

查看下notifyRegistrants的具体实现

http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/os/RegistrantList.java#registrants
   
/**
  * 该方法有较多的重载,最终的实现如下
  * 该函数遍历所有的注册对象,然后向每个对象发出通知
  */  
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);
   }
}


http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/os/Registrant.java
/**
  * 该方法几个关注点:
  * getHandler():在前面Registrant的构造函数里有看到,这个handle为注册时传入的第一个参数
  * 如果该handle不为空,则就是一个handle的消息的send
  */ 
/*package*/ void
internalNotifyRegistrant (Object result, Throwable exception)
{
    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);
    }
}


   即  mRil.mVoiceRadioTechChangedRegistrants.notifyRegistrants(new AsyncResult (null, response, null))执行完后,会告知之前的注册对象现在voice_radio_tech变化了。

从前面的代码来看,GsmCdmaPhone 在向Ril注册时,有三个参数,前两个参数分别是:this & EVENT_VOICE_RADIO_TECH_CHANGED.从之前代码的分析也可以看出,第一个参数的this会最终传到Registrant,作为Registrant构造函数的一个参数,并在最终会通过handler发送出去。第二个参数的EVENT_VOICE_RADIO_TECH_CHANGED 也是作为一个构造函数的一个参数,最终发送回去。

那么最终对于这个消息的接收和处理也就比较好理解了:

http://androidxref.com/8.0.0_r4/xref/frameworks/opt/telephony/src/java/com/android/internal/telephony/GsmCdmaPhone.java#handleMessage
/**
  * 最终的实现
  */ 
        case EVENT_VOICE_RADIO_TECH_CHANGED:
        case EVENT_REQUEST_VOICE_RADIO_TECH_DONE:
            String what = (msg.what == EVENT_VOICE_RADIO_TECH_CHANGED) ?
                        "EVENT_VOICE_RADIO_TECH_CHANGED" : "EVENT_REQUEST_VOICE_RADIO_TECH_DONE";
            ar = (AsyncResult) msg.obj;
            if (ar.exception == null) {
                if ((ar.result != null) && (((int[]) ar.result).length != 0)) {
                    int newVoiceTech = ((int[]) ar.result)[0];
                    logd(what + ": newVoiceTech=" + newVoiceTech);
                    phoneObjectUpdater(newVoiceTech);
                } else {
                    loge(what + ": has no tech!");
                }
            } else {
                loge(what + ": exception=" + ar.exception);
            }
            break;

PS:个人理解,对于该功能的实现,就是那里注册,最终那里接收实现。在某个地方看到了notifyRegistrants,那么就寻找该Registrants的定义,然后查看哪里去register,并且register了什么消息。那么同时也就看到了这个注册消息的实现。

你可能感兴趣的:(Android,基础篇)