Android telephony framework中有Phone.java,PhoneBase.java, GsmPhone.java(或者CdmaPhone), PhoneProxy.java
其中Phone是接口类,剩余三个类都实现了Phone接口,只不过是作用不一样。PhoneBase实现了一些通用的接口;GsmPhone和CDMAPhone,两者层次是对等的,只不过一个实现符合Gsm要求,另一个实现符合cdma的要求;PhoneProxy从名字就能看出是代理类。app层获取的Phone对象实际的类型就是PhoneProxy。
代理模式举例在百度上到处是,不过阐述该模式到底有啥好处的比较少,从网上我看到几种说法:
1.代码解耦。如日志代码可以加入到代理类中,那么日志代码就不会污染实现类的代码,切面编程就是这种思想。
2.系统扩展。写代理类是因为无法修改实现类或者无法继承实现类,设想我用的是三方库,没法修改代码,又要做些修改,用代理模式不错。
3.对象很大或者需要很长时间才能构造完毕的情况。通常见于网络程序,例如一副很大的图片载入时间很长,这时可以用代理表示图片请求,实现类表示正真的下载过程;还有懒加载,当有很多项要加载的时候,全部下载是很费资源的,可以用proxy占位,当需要的时候才正真加载。
本人没有搞过网络编程,虽然写java但是没写过SSH架构的东西,不大好理解动态代理,而且Android源码对于大多数手机厂商是可随意修改的,也不存在无法修改实现类的这个原因。而且见代码片段:
frameworks/opt/telephony/src/java/com/android/internal/telephony/PhoneProxy.java
@Override
public ServiceState getServiceState() {
return mActivePhone.getServiceState();
}
@Override
public CellLocation getCellLocation() {
return mActivePhone.getCellLocation();
}
/**
* @return all available cell information or null if none.
*/
@Override
public List<CellInfo> getAllCellInfo() {
return mActivePhone.getAllCellInfo();
}
/**
* {@inheritDoc}
*/
@Override
public void setCellInfoListRate(int rateInMillis) {
mActivePhone.setCellInfoListRate(rateInMillis);
}
@Override
public PhoneConstants.DataState getDataConnectionState() {
return mActivePhone.getDataConnectionState(PhoneConstants.APN_TYPE_DEFAULT);
}
@Override
public PhoneConstants.DataState getDataConnectionState(String apnType) {
return mActivePhone.getDataConnectionState(apnType);
}
@Override
public DataActivityState getDataActivityState() {
return mActivePhone.getDataActivityState();
}
@Override
public Context getContext() {
return mActivePhone.getContext();
}
基本所有的方法都是直接调用实现类mActivePhone的同名同参方法,没有加任何逻辑代码,那么使用代理模式是为了啥?
其实在PhoneProxy的构造函数中:
mCommandsInterface.registerForVoiceRadioTechChanged(
this, EVENT_VOICE_RADIO_TECH_CHANGED, null);
向ril注册了监听网络制式变化的消息
case EVENT_VOICE_RADIO_TECH_CHANGED:
...
phoneObjectUpdater(newVoiceTech);
...
break;
消息处理中调用phoneObjectUpdater
private void phoneObjectUpdater(int newVoiceRadioTech) {
...
deleteAndCreatePhone(newVoiceRadioTech);
...
mIccSmsInterfaceManager.updatePhoneObject((PhoneBase) mActivePhone);
mIccPhoneBookInterfaceManagerProxy.setmIccPhoneBookInterfaceManager(mActivePhone
.getIccPhoneBookInterfaceManager());
mPhoneSubInfoProxy.setmPhoneSubInfo(mActivePhone.getPhoneSubInfo());
mCommandsInterface = ((PhoneBase)mActivePhone).mCi;
mIccCardProxy.setVoiceRadioTech(newVoiceRadioTech);
...
}
删除了原有的Phone对象,依据新的网络制式建立了新的Phone对象,然后更新各个代理类的实现类。那么telephony framework中的代理类作用其实就是可以切换实现类而对上层app没影响(消除了实现类变化对使用代理类代码的影响),试想如果上层app直接使用GsmPhone或者CdmaPhone,那么网络制式切换造成的影响可就很大了。
较早的时候切换网络制式这种现象是很罕见的,只有电信国际漫游在某些国家会由cdma切换到gsm,不过现在到处是全网通机器,这种现象比较普遍了。