装饰模式
以我们最熟悉的Context为例,它就是一种装饰模式。
我是这样理解的,Context是一个抽象的人,没有具体指谁,ContextImpl是一个裸男,ContextWrapper是一个穿好衣服的人,而Service,Activity和Application就是三个穿着不同衣服,有不同角色的人。
抽象类Context,定义了一系列的接口,用getResources作为例子。
public abstract Resources getResources();
真正的实现类是ContextImpl。
@Override
public Resources getResources() {
return mResources;
}
而ContextWrapper是一个包装作用,虽然它也继承了Context,但是不负责核心功能的实现,它的内部有一个Context类型的成员变量mBase,核心功能是调用mBase实现的。
@Override
public Resources getResources() {
return mBase.getResources();
}
每一个Wrapper可以根据需要在mBase的基础上添加自己的装饰。开发者根据需要编写不同的ContextWrapper子类,比如我们最熟悉的四大组件,Activity,Service,Application都是ContextWrapper的子类,它们都是对Context的装饰。
mBase变量通过attachBaseContext方法传递给ContextWrapper。
protected void attachBaseContext(Context base) {
if (mBase != null) {
throw new IllegalStateException("Base context already set");
}
mBase = base;
}
所以我们熟悉的四大组件都有一个attach方法。比如Service如下:它会需要获取Application,AMS等实例对象。
@UnsupportedAppUsage
public final void attach(
Context context,
ActivityThread thread, String className, IBinder token,
Application application, Object activityManager) {
attachBaseContext(context);
mThread = thread; // NOTE: unused - remove?
mClassName = className;
mToken = token;
mApplication = application;
mActivityManager = (IActivityManager)activityManager;
mStartCompatibility = getApplicationInfo().targetSdkVersion
< Build.VERSION_CODES.ECLAIR;
}
而Activity需要设置或者获取一些窗口属性。
@UnsupportedAppUsage
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
mUiThread = Thread.currentThread();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mAssistToken = assistToken;
mIdent = ident;
mApplication = application;
mIntent = intent;
mReferrer = referrer;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
if (voiceInteractor != null) {
if (lastNonConfigurationInstances != null) {
mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
} else {
mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
Looper.myLooper());
}
}
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
mWindow.setColorMode(info.colorMode);
setAutofillOptions(application.getAutofillOptions());
setContentCaptureOptions(application.getContentCaptureOptions());
}
代理模式
我们最熟悉的Binder通信就是一种代理模式。
以一个最简单的AIDL为例,我们定义一个IReportInterface.aidl,声明一个report接口。
int report(String key, int value);
编译之后会自动生成一个IReportInterface.java文件。主要有两个类,Stub和Proxy。
Stub类是给服务端使用的,它是一个Binder对象,同时实现了IInterface接口。
public static abstract class Stub extends android.os.Binder implements com.one.binder.IReportInterface {
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public static com.one.binder.IReportInterface asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.one.binder.IReportInterface))) {
return ((com.one.binder.IReportInterface) iin);
}
return new com.one.binder.IReportInterface.Stub.Proxy(obj);
}
@Override
public android.os.IBinder asBinder() {
return this;
}
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
java.lang.String descriptor = DESCRIPTOR;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_report: {
data.enforceInterface(descriptor);
java.lang.String _arg0;
_arg0 = data.readString();
int _arg1;
_arg1 = data.readInt();
int _result = this.report(_arg0, _arg1);
reply.writeNoException();
reply.writeInt(_result);
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
}
而客户端使用Proxy类。
private static class Proxy implements com.one.binder.IReportInterface {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}
@Override
public int report(java.lang.String key, int values) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(key);
_data.writeInt(values);
boolean _status = mRemote.transact(Stub.TRANSACTION_report, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
return getDefaultImpl().report(key, values);
}
_reply.readException();
_result = _reply.readInt();
} finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
public static com.one.binder.IReportInterface sDefaultImpl;
}
当客户端调用report方法时,会通过一个IBinder对象mRemote把数据传送给服务端。
服务端的onTransact方法被调用,根据transaction code,会调用服务端的report方法,并且把结果返回给客户端。
观察模式
我们最熟悉的广播是一种观察模式。
广播队列可以理解成一个观察对象,广播接受者是观察者。
我们不需要关注每一个广播的细节,它们都是抽象的广播类型。
首先AMS内部维护了一个hashMap结构,保存了广播接受者和对应的IntentFilter列表的键值对。一个应用可以同时监听多个广播,一个广播也可以同时发给多个应用。
final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();
这里的IIntentReceiver是一个aidl接口,用到了上面介绍的代理模式。
服务端是在LoadedApk中实现的,继承了Stub类,实例化了一个本地对象InnerReceiver。
final static class InnerReceiver extends IIntentReceiver.Stub {
final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
final LoadedApk.ReceiverDispatcher mStrongRef;
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
mStrongRef = strong ? rd : null;
}
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
final LoadedApk.ReceiverDispatcher rd;
if (intent == null) {
Log.wtf(TAG, "Null intent received");
rd = null;
} else {
rd = mDispatcher.get();
}
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction()
+ " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
}
if (rd != null) {
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
} else {
// The activity manager dispatched a broadcast to a registered
// receiver in this process, but before it could be delivered the
// receiver was unregistered. Acknowledge the broadcast on its
// behalf so that the system's broadcast sequence can continue.
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing broadcast to unregistered receiver");
IActivityManager mgr = ActivityManager.getService();
try {
if (extras != null) {
extras.setAllowFds(false);
}
mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
}
最终,每一个广播变化,都通过AMS中的广播队列,最终由LoadedApk.ReceiverDispatcher通知给每一个广播监听器。